Asynchronous Programming Considerations
When implementing an OSP simple provider, it is the consumer's responsibility to marshal notification between threads. The consumer has two choices of threading models: free-threaded or apartment. Each is explained in Consumer Threading Responsibilities, in the OLE DB Programmer's Reference. The way notifications are handled in the two threading models is described in Threading and Notifications.
This feature will be removed in a future version of Windows. Avoid using this feature in new development work, and plan to modify applications that currently use this feature. Instead, write a fully functional OLE DB provider using the native OLE DB interfaces.
Asynchronous processing enables methods to return immediately without blocking on the calling thread. Consumers must explicitly request asynchronous processing when initializing a data source object or when opening or populating a rowset. Otherwise, the provider can perform asynchronous operations in the background but must behave synchronously, blocking if necessary, until the underlying asynchronous operation completes. For more information about asynchronous behavior in OLE DB, see the topics Asynchronous Processing and Asynchronous Rowset Population.
If an asynchronous OLE DB simple provider spawns a thread to populate rows and sends notifications from within that thread, it cannot call notification methods on the OLEDBSimpleProviderListener interface for that spawned thread. Instead, in the implementation of OLEDBSimpleProvider::addOLEDBSimpleProviderListener, the OSP should marshal IID_IOLEDBSimpleProviderListener to a stream object. Marshaling can be accomplished using CoMarshalInterThreadInterfaceInStream, or simply, CoMarshalInterface. The OSP may need a list of the listeners since multiple listeners are possible, depending on whether the threads are multicast or single cast.
Before calling any notification methods, within the asynchronous thread, the OSP must unmarshal the stream object into an interface within that thread. Because the streams were set up before the thread was started, the procedure is as follows:
Call CoGetInterfaceandReleaseStream, or simply, CoUnmarsalInterface, for IID_IOLEDBSimpleProviderListener.
Call the notification methods directly from the interface (now that it has been marshaled to this thread).
If the threading model is apartment, which means CoInitialize was called, the consumer must have a message pump within the apartment model thread to push a copy of the same message (or notification) onto each thread. This is done by using MsgWaitForMultipleObjects to pump any waiting COM messages through each thread between the population of rows.