DAO and the Apartment-threading Model

DAO 3.5 can be used in several threads of a multi-tasking application to accomplish many tasks simultaneously. For example, a long running query may be performed by one thread, while the contents of a large recordset may be displayed by another thread.

This is possible because DAO 3.5 is an inproc (DLL-based) server which supports the OLE Apartment-threading Model. The Apartment-threading Model defines one way interface calls are made to an OLE object and how interface pointers are passed between threads.

Characteristics of the Apartment-threading Model

The Apartment-threading Model is characterized by these attributes:

Client Responsibilities in the Apartment-threading Model

The client responsibilities in the Apartment-threading Model are listed below:

Only Unicode Interfaces can be Marshaled

The DAO 3.5 SDK includes several versions of its DLLs. However, DAO only supports the Unicode interfaces for multi-threading. This is because DAO relies on OLE to do marshaling and OLE is based on Unicode. This also means that because Microsoft Windows 95 does not fully support Unicode, DAO can not be used in multiple threads on Windows 95.

In the example below, the DAO 3.5 client creates a shared DBEngine in one thread, and then marshals the DBEngine interface to another thread that accesses the DBEngine. The interface is acquired with the GetInterface DAO method (see "Using DAO Interfaces").

(Error handling excluded for readability):

UINT TestThread(LPVOID);
LPSTREAM pstmDBEngine;

UINT TestThread(LPVOID pParam)
{
CdbDBEngine *pengine;
DAODBEngine *pIdben;
   TRACE("Hello");

   CoInitialize();
   CoGetInterfaceAndReleaseStream( pstmDBEngine, 
            IID_DAODBEngine, (void **) &pIdben);
   pengine = new CdbDBEngine(pIdben, TRUE);
   pengine->GetVersion();   // Now you can use DAO.
   delete pengine;
   TRACE("Goodbye");
   return 0;
}

void CEnginetestDlg::OnOK() 
{
CdbDBEngine   engine;
DAODBEngine   *pIdben;
CWinThread    *pThread;
MSG          msg;

pIdben = engine.GetInterface();
pThread = AfxBeginThread(TestThread, this, 
               THREAD_PRIORITY_NORMAL, 
               0, CREATE_SUSPENDED);
CoMarshallInterThreadInterfaceInStream(
               IID_IDAODBEngine, pIdben,
               &pstmDBEngine);
pThread->ResumeThread();

// Now, go into a message loop. This is a requirement // for apartment-model threading.
for (;;)
   {
   if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
      {
      TranslateMessage(&msg);
      DispatchMessage(&msg);
      }
   }
}