Dear Sir,
I am a software engineer with Yokogawa Electric Corporation in Japan.
I have a question about firing events from a second thread.
I am going to try to make an ActiveX in-proc server that uses the apartment-threading model, creates a thread, and fires events.
I read the following article from the Knowledge Base: "FIREEV.EXE Fires Events from a Second Thread" (Article ID: Q157437).
This article said, "Because MFC ActiveX controls use the apartment-threading model, special consideration must be taken when firing events from a secondary thread. We should not fire events from a second thread. Events must be fired from a main thread."
Also, I read the following article: "Events: From an ATL Server to a Visual Basic Sink" (Microsoft Developer Network News Online, May 15, 1997).
A sample program provided in this article fires events from a second thread.
Is it possible to fire events from a second thread?
I'm looking forward to the answer from you.
Thanks in advance.
Sincerely,
Shinichi Shimizu
Dr. GUI replies:
When sewing a program together, it's important to use the right sutures, or threads. In general, it's best in apartment model to fire events only from the thread on which the control was created. If you start other threads, you should post a message to the main thread to tell it to fire the event.
The sample that you have found indeed only demonstrates one technique for firing events from a secondary thread. It discusses the method whereby the secondary thread posts a message to the primary thread, which actually fires the event by calling the method in the event sink.
It is possible, however, to fire an event directly from the secondary thread. As the article mentions, it is necessary to marshal the interface pointer of the event sink (usually received via a call to IConnectionPoint::Advise()) so it is suitable for use by the secondary thread and to pass that pointer to the secondary thread. This is not discussed in detail by the FIREEV.EXE article; however, it is not difficult. The essential API pairs used to accomplish this are CoMarshalInterface()/CoUnMarshalInterface() and CoMarshalInterThreadInterfaceInStream()/CoGetInterfaceAndReleaseStream(). The first API marshals the interface and prepares a stream to be used by the secondary thread when it calls the second API to unmarshal the interface. Once you have done this, the interface is ready to be used to call the event sink directly. An example of using CoMarshalInterface() is in a Platform SDK sample called OLEAPT. CoMarshalInterThreadInterfaceInStream() and its partner are more convenient versions.
A note: Dr. GUI once had to give mouth-to-mouth resuscitation to a foolish developer who stopped breathing after attempting to pronounce "CoMarshalInterThreadInterfaceInStream" without taking a breath. So don't try this at home.