Platform SDK: MAPI |
With objects that are returned from interface method calls directly, it is the provider's responsibility to ensure thread-safety. With callback objects, it is the client's responsibility. A service provider implements a thread-safe object by serializing access to shared data within the object, insuring that one thread does not inadvertently replace the work of another thread. A service provider can implement serialized access to data in three ways:
A client can implement a thread-safe notification callback by calling the MAPI utility HrThisThreadAdviseSink. HrThisThreadAdviseSink transforms a non-thread-safe advise sink into a thread-safe one. For progress callbacks, there is no such utility at this time. A client can choose to use the MAPI thread-safe progress object or create one manually.
A thread-safe object might or might not also be thread-aware. A thread-aware object maintains a separate context for every thread that is using it. Service providers are not required to support thread-awareness in their thread-safe objects, although supporting thread-awareness can be useful in some situations. Two MAPI tables always provide their own context by definition. One table used on different threads does not and should not provide unique context.
A client can choose between receiving notifications on the same thread that was used for the MAPIInitialize call, on the same thread that was used for the Advise call, or on a separate thread owned by MAPI. To ensure that notifications arrive on the same thread that was used to call MAPIInitialize, a client calls MAPIInitialize and passes zero in the ulFlags member of the MAPIINIT_0 structure. Notifications are then delivered during the main message loop.
To receive notifications on the MAPI-owned thread, a client calls MAPIInitialize with the ulFlags member of the MAPIINIT_0 structure set to MAPI_MULTITHREAD_NOTIFICATIONS. The Advise call is made with the client's advise sink object rather than a wrapped version.
To ensure that notifications arrive on the same thread that was used to call Advise, a client calls HrThisThreadAdviseSink and passes the newly created wrapped advise sink to Advise rather than the original advise sink. MAPIInitialize can be called with either flag value.