none
C# worker thread calls com server and WaitForSingleObject times out unexpectedly. RRS feed

  • Question

  • I recently read the quality response to this posting "Thread Issue in C++ COM Server after C# call COM Interface" by Lim Bio Liong and that gave me hope that someone could explain a failure we are seeing.  We have a legacy MFC dll with a COM method that starts a data pump. The method is called Start and the first line of code in the function is DWORD iWait = WaitForSingleObject( eventStartingPump, 10000 ); The class containing the Start method is constructed when the dll is loaded. The event object, eventStartingPump, is created as signaled in the constructor of the class. The Start method is called from a COM interface class. The interface method is called by a C# worker thread that waits here Monitor.Wait (m_locker); and is released by the C# main thread in OnRender by calling Monitor.Pulse (this.m_locker);  On the C++ side the event handle is declared as static and initialize as HANDLE Foo::eventStartingPump = NULL; In the class constructor the event is created like so:

       eventStartingPump = ::CreateEvent(NULL, // no security attributes
          FALSE, // manual-reset
          TRUE, // initially signaled
          NULL);// anonymous


    The WaitForSingleObject was chosen both to prevent more than one thread running in the function and to enforce a long delay of a second thread before returning. The problem is that this works about 95% of the time as expected but about 5% of the time the WaitForSingleObject times out. We have instrumented the code to ensure the execution is as expected both in the constructor and within the start function. If the WaitForSingleObject doesn't time out on the first execution after the program starts it will always execute as expected. The failure is that the first thread to enter the function times out about 5% of the time. However, once it fails it will always fail unless we change the code to call SetEvent(eventStartingPump); after the time out. In other words the event object is acting as though it was not created as signaled. This interface worked 100% of the time when it was MFC GUI to MFC server. 

    Thursday, August 2, 2018 7:09 PM

All replies

  • <guess> IIRC there can be some weirdness doing stuff from dllmain(). So you might try creating the event in a method after the DLL is loaded</guess>

    If you have only the one C# client app for this DLL, I would push all the synchronization into the C# code.  You already have a Monitor wait loop there.  Even if this is an out-of-process COM server, you can do cross-process synchronization from C# with a named Mutex.

    Otherwise you'll probably have to build a simplified repro to figure this out.  It will turn on some horrible old detail of the COM threading models. :(

    David


    Microsoft Technology Center - Dallas
    My blog

    Thursday, August 2, 2018 7:53 PM
  • Thanks for your response. So the short answer is I have two clients although that does not preclude putting all of the synchronization on the C# side it was the more complex solution since the synchronization worked with MFC. On entry to the screen, OnRender(first time only) pulses the  Start method. Once the screen is displayed a button can restart the data pump by pulsing it's own worker thread that calls the same Start method. If the data pump is running the restart button should be disabled. Also, I should have mentioned that it is an in-process COM server.

    Along the line of your guess we have tried calling SetEvent(eventStrtPump) later in the sequence and that does seem to work but I was hoping to get at the root cause so as not to get bit in the future. It can take 20-30 tries to get a failure and each try takes about 5 minutes so that is 2-3 hours work for each patch and with such a low failure rate even that testing is not conclusive.

    Thursday, August 2, 2018 8:45 PM
  • Hi NPCraig,

    I would suggest that you could write log function, which records the every steps of information and check what steps cause the issue. 

    In addition, as david said, please try Mutex to synchronize different process.

    Best regards,

    Zhanglong 


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Wednesday, August 8, 2018 5:37 AM
    Moderator