DAO multi-threading tips

.

Download sample project


Looks like DAO 3.5 has some support for multi-threading.

As stated by the MFC 4.2 documentation, the Dao database classes are not thread-safe, and that is indeed true.

I recently developed a server application the uses IO completion ports, which by nature, are using a number of threads. Because of that, I had to figure out a way to use DAO in different threads simultaneously. Here is how I did it:
//
// used a global critical section to prevent multiple threads initializing 
// the Dao database simultaneous.
//
CCriticalSection cs;

//
// Some thread function
// (In my server app, 4 thread using this function is started)
//
UINT MyThreadFunc (LPVOID pParam)
{
	CSingleLock lock(&cs, TRUE);

	//
	// Initialize MFC Dao support
	//
	AfxDaoInit();

	CDaoDatabase db;
	CSomeDaoRecordset set(&db);
	

	// 
	// Open the database and recordset.
	//
	try
	{
		db.Open(_T("database.mdb"));
		set.Open(dbOpenTable);
		set.SetCurrentIndex(_T("PrimaryKey"));
	}
	catch(CException* pe)	
	{
		pe->ReportError();
		pe->Delete();
		return 0;
	}

	//
	// Allow other threads to initialize Dao
	//
	lock.Unlock();
	

	//
	// OK the database and recordset is now open
	//

	while( bRunThisThread )
	{
		//
		// NOTE: You do NOT need to lock out other threads vhile calling
		// database functions here.
		//
		WaitForClientRequest();
		ParseRequest();
		DoDatabaseIO();
	}

	//
	// Now, lock the critical section again
	//
	lock.Lock();

	//
	// Close recordset and database.
	rs.Close();
	db.Close();

	// IMPORTANT: do NOT call AfxDaoTerm() !!!!
	return 0;
}

Now, when your application terminates, it will generate a protection error. To prevent that modify your CMyApp::ExitInstance().

int CMyApp::ExitInstance()
{
	// 
	// Insert your own cleanup code here
	//

	AfxDaoInit();
	AfxDaoTerm();
	
	return m_msgCur.wParam;
}

Notes:
7 The MFC documentation says the you need to call AfxBeginThread to start worker threads, but this is not necessary at all times, it depends on what your doing in your thread function. (I use both AfxBeginThread() and ::CreateThread()).
7 I call AfxBeginThread() in my main InitInstance() function, but I am not really sure if this is necessary. Of course, you should do it if you need to access the database from your main thread.
7 You will not gain true multithreaded access to the database functions. Jet 3.5 serializes the function calls, but the threads do not have to worry about that.

Known problems:
1. I have discovered that this approach can sometimes prevent other applications from starting, like MS Word 97, they simply hang, but when i shutdown my multithreaded Dao app, they continues as though nothing has happened ?????
2. My spelling :-)
3. ::CoInitialize() will be called for every call to AfxDaoInit(), and will not all be matched by a call to :: ::CoUninitialize(), but i hope the Windows will clean up the mess.



Comments

  • No Different Threads---

    Posted by Legacy on 08/01/2003 12:00am

    Originally posted by: Siddharth

    I put this solution in my project and its seem to work for first thread and if i invoke another thread containing AfxDaoInit from the first thread its giving runtime error
    Abnormal Programme Termination but its running perfectly alright on Win2000 server but not on winME

    Reply
  • Danke

    Posted by Legacy on 02/18/2003 12:00am

    Originally posted by: jan

    thank you for this elegant and usful piece of code.

    Reply
  • provide good online coaching

    Posted by Legacy on 12/24/2002 12:00am

    Originally posted by: phani bhushan reddy

    respected sir,
    here iam happy to get this option , to share my views/problems with you. sir i found one problem while i was using brain bench site.i didnot know about com and dcom.
    i want to know about that if any chances are there for it
    please specify through mail .
    if my request is not glad to receive please excuse me.
    thanking you,
    i hope the best

    Reply
  • TH

    Posted by Legacy on 08/09/2002 12:00am

    Originally posted by: Gabor M�lyi

    Thank You!

    Your's programs great, and able piece of my work.

    Gabor

    Reply
  • Thank you

    Posted by Legacy on 02/25/2002 12:00am

    Originally posted by: Chetan

    Your article saved me from lots of Multi threading issues I encountered due to DAO.

    Thanks again.

    Reply
  • Muchos Gracias!

    Posted by Legacy on 12/28/1999 12:00am

    Originally posted by: Zenon

    After racking my brain for hours on end, I finally consulted CodeGuru, and voil�, the answer was there waiting for me.

    Many thanks to John Bundgaard who just made my life a whole lot easier.

    Reply
  • Restart IDE

    Posted by Legacy on 05/17/1999 12:00am

    Originally posted by: James Johnston

    Have you restarted the Visual Studio IDE?

    Reply
  • Unlock the lock?

    Posted by Legacy on 01/15/1999 12:00am

    Originally posted by: Morten Tor Nielsen

    When the thread is done with the database the database objects are closed.

    That piece of code is executed in a monitor (the entrance is the lock.Lock() statement) but don't you need a lock.Unlock() statement after the closing of the DAO objects (or does the CSingleLock unlock when you exit scope??)

    Otherwise thanks for the tip - VERY Very helpfull

    Morten

    Reply
  • Mutli Threaded DAO

    Posted by Legacy on 01/13/1999 12:00am

    Originally posted by: Jeff Miller

    A client had a problem with the DAO code crashing when used in multiple threads. There were several million lines of code. To touch the minimal amount of code, I came up with a way to force all of the DAO calls to go through the GUI thread. If anyone is interested in this approach, I can post the code.

    Reply
  • Stop other programs starting until Database program terminated

    Posted by Legacy on 11/18/1998 12:00am

    Originally posted by: Steve Westgate

    I had a similar problem of other programs not starting until the databse program was terminated and they then
    continued to startup.
    
    

    Looking at the help on DAO you need to add a message dispatcher routine in your threads loop.

    For example

    if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
    {
    TranslateMessage(&msg);
    DispatchMessage(&msg);
    }

    Reply
  • Loading, Please Wait ...

Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • Live Event Date: December 11, 2014 @ 1:00 p.m. ET / 10:00 a.m. PT Market pressures to move more quickly and develop innovative applications are forcing organizations to rethink how they develop and release applications. The combination of public clouds and physical back-end infrastructures are a means to get applications out faster. However, these hybrid solutions complicate DevOps adoption, with application delivery pipelines that span across complex hybrid cloud and non-cloud environments. Check out this …

  • On-demand Event Event Date: October 29, 2014 It's well understood how critical version control is for code. However, its importance to DevOps isn't always recognized. The 2014 DevOps Survey of Practice shows that one of the key predictors of DevOps success is putting all production environment artifacts into version control. In this webcast, Gene Kim discusses these survey findings and shares woeful tales of artifact management gone wrong! Gene also shares examples of how high-performing DevOps …

Most Popular Programming Stories

More for Developers

RSS Feeds