Inter Thread Communication in Apartment Threading Model of ATL Component

Environment: VC6, Win NT4, Win 2000

Hi EveryBody,

This time I'm providing a solution to the very basic concept of Inter Thread Communication. In the Apartment threading model of COM, if we have to communicate between two apartments of threads, then we need marshalling of the first thread object to the second thread. If we have to access the primary thread data then we need to marshal the interface pointer from the primary thread to the second thread. This is the case when we are restricted to thread boundries just because we chose the Apartment threading model.

The solution is marshalling. We have to accept that we don't all want to put ourselves into marshalling. Sometime we work to avoid this kind of marshalling code.

The solution that I have implemented is to use window messge routing for inter thread communication. If we are implementiong activeX controls in ATL, then we can use a control's message routing. If we are developing a simple COM object without any window, then we have to create a hidden dummy window to use as a medium.

In my sample code, I have a simple COM object that supports the connection point and apartment threading model. I have one event that I have to fire from a secondry thread of same COM object.

As I told you earlier, I'm using a non-windowed simple COM object. To use window messge routing, you have to create a window using the CWnd class. I'm using my own class that I derived from CWnd with the name of CMyTempWindow. In the Create method I created a window without any style:

HWND CMyTempWindow::Create()
{
  LPCTSTR classname = 0;
  classname = AfxRegisterWndClass(0);

  // Create the window and return it's handle
  CWnd::CreateEx(NULL,classname,NULL,NULL,1,1,1,1,NULL,NULL);
  ASSERT(m_hWnd!=NULL);
  return m_hWnd;

}

In this window class I have implement one my user defined message handler to fire the event from that handler. To implemnt that I define one user define ID as:

#define WM_THREADFIREEVENT WM_USER+101

And it's handler

LRESULT CMyTempWindow::OnFireEventForThread(WPARAM wParam,
                                            LPARAM lParam)
{
  //This is a one-message-does-everything handler.  If 
  // wParam is not set, that means our message has been
  // sent to fire the even. If wParam is set that means
  // we're being asked to destroy ourselves
  if(!wParam)
     m_pControl->Fire_Checkevent();
  else if(wParam==1)
     DestroyWindow();

  return TRUE;
}

Now I have exposed one method of my COM object in which I'mm just creating the window and firing second thread with a window object to post the message on dummy window. That is:

STDMETHODIMP CObjectThread::BeginThread()
{
  AFX_MANAGE_STATE(AfxGetStaticModuleState())

  // TODO: Add your implementation code here
  CMyTempWindow *pWnd = new CMyTempWindow(this);
  HWND hwndTarget = pWnd->Create();
  AfxBeginThread(ThreadProc,(LPVOID)hwndTarget);

  return S_OK;
}

Now the final and most importent issue is the secondary thread procedure in which I'm posting the user defined message to the dummy window in order to fire the event of outgoing interface. The event would be mapped to the client site for notification. In order to avoid marshalling you means you can't fire the secondary thread event directly with an interface pointer because of the apartment model. By using window message routing as the medium to fire event from the primary thread of COM object, if you try to fire the event directly from the secondry thread you will see the difference. What will happen? The boundry of secondary thread will be in the primary thread and at your client site mapped event you will basically have an infinity loop and won't be able to get out of that event. Because an apartment boundry is not there to freely execute the secondary thraed.

To make second thread free and independent, after firing the primary thread event, this is the only way:

UINT ThreadProc(LPVOID pParam)
{
  // Simulate a lengthy process
  Sleep(2000);

  // Use this code if your control has a window
  // CObjectThread *pCtrl = (CObjectThread*)pParam;
  // PostMessage(pCtrl->m_hWnd,WM_THREADFIREEVENT,
  //                      (WPARAM)NULL,(LPARAM)NULL);

  //Use this code if your control doesn't have a window and is
  HWND hWnd =  (HWND)pParam;

// going to use the CMyTempWindow class to send messages 
  // to the control
  for(int i =0; i<10; i++) 
  {
    if(i==4)
    {
       PostMessage( hWnd,
                    WM_THREADFIREEVENT,
                    (WPARAM)NULL,
                    (LPARAM)NULL);
    }
    AfxMessageBox("Trial");
  }

  PostMessage( hWnd, 
               WM_THREADFIREEVENT,
               (WPARAM)1,
               (LPARAM)NULL);
  return 0;
}

In the case where you are using an activeX control and using a control window, just create a user define message handler in the control class as I have done in the dummy window class.

This is one of my tries for getting more knowledge on the apartment threading model and secondary thread issues with events. If I'm lacking somewhere, guidence would be appreciated.

As I stated earlier, I'm using a simple COM object from ATL so to map the event's on the client side you have to refer to an article in MSDN:

Q181845 HOWTO: Create a Sink Interface in MFC-Based COM Client

Thanks

Pardeep.

Downloads

Download source - 84.5 Kb


About the Author

Pardeep Kadian

Be young by heart, sharp by mind.
doesn't matter to have a whisky or wine.
Neither it belong to you nor mine.
Keep learning to always have a shine.

Comments

  • eovvycis

    Posted by frppycvd on 04/22/2013 03:55pm

    qihlpnqf http://casquebeatsbydreoffzhot.fr/ nywizaub http://salzchaneloutletoffr.com/ dteoyasz http://nowsalzhollisteroutlet.co.uk/ btppshyj http://coolralphlaurenpascheroffz.fr/ cwmivplr http://louisvuittonhandbagsoffzhot.com/ ouiumykc casque beats by dre ghweftpv chanel outlet fgnvizto hollister outlet kyklavxw ralph lauren pas cher snmfsoym louis vuitton handbags Seniors the fact that find automobile insurance will see in which your levels will probably be reduced should they may show some clean cruising back ground. In that possition, you'll be able to exploit the multi-vehicle price reduction. To provide a problem of actuality, the process in operating a blog instantly isn't a fresh new strategy for you to people who have a friend considering the operating a blog globe.

    Reply
  • ymqwjkzc

    Posted by wuumrltz on 04/22/2013 10:19am

    swjbjxoa http://oakleysunglassesaustraliao.co.uk/ znpehcqc http://casquebeatspascherq.fr/ xojihhmc http://louisvuittonwalletet.com/ ooxsizjv http://hollisteroutletlet.co.uk/ pxucxrjh http://todsbagndrivingshoese.com/ ztbixvyl oakley sunglasses australia hxzgouoz casque beats pas cher qmadbuhy louis vuitton wallet yfgjiowb hollister outlet fopgmvvz tods bag I find myself including nike will accept abounding affronted barter using the 2010 air the nike jordan footwear... Get rerouted physician and also take allergies evaluation, before spending your remedies. When you've obtained as often documentation since you can easily, you'll want to ensure that you exchange coverage details considering the some other person.

    Reply
  • Good article

    Posted by BSDahiya on 10/10/2008 05:37am

    Nice tutorial.

    Reply
  • Static.......

    Posted by Legacy on 05/01/2002 12:00am

    Originally posted by: Pardeep

    Hi Dan,
    i think u r also facing the same what i was ... and the solution what u r thinking is a right way , as per Q if u will use MSMQ then i think it would be unneccesary overhead on application , first try to fire the event using the way in dummy window.
    and if ur com object is having there on message map then u can post the message in ur com object routing also.
    But be sure ur API call should be in the same process.
    may help u .......
    pardeep

    Reply
  • static member functions and connection points

    Posted by Legacy on 04/30/2002 12:00am

    Originally posted by: Dan Perrin

    I have a similar problem, and seen as you have worked a bit on this topic, your comments would be appreciatd. 
    
    

    Windowless ATL COM Object, apartment threaded.

    I have a static callback member function that gets fired externally from the RAS API. In the callback function I reference a global pointer that allows me to to fire a connection point event : viz.

    MyMainClass * _pMyMainClass; //global

    MyMainClass::MyMainClass()//constructor
    {
    _pMyMainClass = this;
    }

    VOID WINAPI MyMainClass::MyCallback(DWORD dwSomeValue)
    {
    _pMyMainClass->Fire_MyEvent(dwSomeValue);

    }

    The COM object is used from a test VB app. The problem is I get an exception error from the VB runtime, and I assume the reason is because the static callback is in another thread. I have thought of a few solutions. One is creating a dummy window and doing a postmessage() from the static callback, the other is placing the event on a Q, and then posting a message (I don't know how as yet) to the COM objects message map. This would then generate an event would would allow the Fire_MyEvent() to be fired.

    Any comments on this?

    Thanks

    Dan

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

Top White Papers and Webcasts

  • This paper introduces IBM Java on the IBM PowerLinux 7R2 server and describes IBM's implementation of the Java platform, which includes IBM's Java Virtual Machine and development toolkit.

  • A modern mobile IT strategy is no longer an option, it is an absolute business necessity. Today's most productive employees are not tied to a desk, an office, or a location. They are mobile. And your company's IT strategy has to be ready to support them with easy, reliable, 24/7 access to the business information they need, from anywhere in the world, across a broad range of communication devices. Here's how some of the nation's most progressive corporations are meeting the many needs of their mobile workers …

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds