none
Does WaitOne() wait unmanaged threads? RRS feed

  • Question

  • Hello-

    I am working on a bit of a strange problem and I'm not sure if the issue is relivant to this form (issue with my C# code) or VB6, but I will ask here anyway.

    I have a VB6 app the has a 300ms timer which used to poll a serial port to check for new data, but it seems like with newer (faster) computers this isn't working so I decided to switch it to using the managed serial port object.  I am using a COM interface and an AutomaticResetEvent to force the call into the managed code to be syncronous.

    I am running into an issue where if either the timer or the UI thread (they are actually the same) are waiting on the AutomaticResetEvent::WaitOne() for the serial port to return, the other one becomes active.

    I have found three blog posts about this, but they all seem to be pretty old and I am wondering if this is a problem or if there are other ways to solve it.

    Blog Posts:

    http://blogs.msdn.com/b/cbrumme/archive/2003/04/17/51361.aspx

    http://blogs.msdn.com/b/cbrumme/archive/2004/02/02/66219.aspx

    http://stackoverflow.com/questions/896233/how-to-wait-on-waithandle-without-message-pumping

    So basically I am asking, is the main point, that if a managed thread that is "tied" to an unmanaged thread, is waiting on a WaitHandle::WaitOne(), then is the unmanaged thread's message pump still active? Is there a way to get around this? Would spawning a worker thread then "Joining" the main thread to that work? Or would it have the same issues?

    Thanks,

    -Tyzack

    • Moved by Bob Shen Thursday, October 4, 2012 6:49 AM (From:Visual C# General)
    • Moved by Sheng Jiang 蒋晟 Thursday, October 4, 2012 10:16 PM System.Threading (From:Where is the Forum For…?)
    Wednesday, October 3, 2012 1:28 PM

All replies

  • Hi tyzack,

    Thank you for visiting the MSDN forum. I’m afraid that it is not the correct forum about this issue. I am moving your question to the moderator forum ("Where is the forum for..?"). The owner of the forum will direct you to a right forum. Thanks for your understanding.


    Bob Shen [MSFT]
    MSDN Community Support | Feedback to us

    Thursday, October 4, 2012 6:49 AM
  • You should not wait in the UI thread as your VB6 code is likely STA-based and requires the message pump to be running.

    Create a background thread to do the serial port communication.



    Visual C++ MVP

    Thursday, October 4, 2012 10:18 PM
  • Hi tyzack

    Your explanation is a little ambiguous. Please describe a little more in detail so that we can help you better.

    • AutoResetEvent can not be shared among different processes. If you have two different apps you should use EventWaitHandle and pass an EventResetMode.AutoReset enum value to its constructor when instantiating it.
    • Which one calls WaitOne() and which one calls Set()? Managed or unmanaged? 
    • If a UI thread waits under a WaitHandle it will be blocked, it can not respond to any other event and its forms will be frozen. So normally you should not call WaitOne() in a UI thread.
    • There are different timers in .NET. Some are single-thread and some are multi-thread. Which one have you used? If you have used Windows.Forms.Timer which is single-thread and is dependent to UI thread, when the UI thread is blocked your timer will be blocked as well.
    • What does the COM interface do?

    What I can say about your last statement is that the answer is both "yes" and "no". Because it depends on whether the unmanaged thread is also waiting for the WaitHandle or not. If it's waiting then it's been blocked and its message pump has stopped working.

    The most important is that you should be careful the thread which will call Set() and send the signal to blocked threads is not blocked itself. Otherwise you will face deadlock.

    Friday, October 5, 2012 7:39 AM
  • To Sheng-

      I am aware that I should not wait the main thread. The original VB6 code used a busy-waiting loop:

    	Do
    
    		strBuf = MSComm.Input
    
    		i = i + 1
    
    	While (i < 3000)

    So that the caller of the "Send" function thought that the response was synchronous. I am trying to implement that save behaviour, though using the managed (C#) SerialPort class. All of the synchronization objects exist in the managed class, and, in theory, there is only one thread running - the main app thread of the VB6 program. If I put in trace statements, the "ManagedThreadId" of the caller to the managed Send method is always the same - event when it is waiting!

    The sequence is:

    [VB6] (event) -> SendCommand -> [COM wrapper class around SerialPort] -> Send.

    I write the command to the serial port then issue a wait on an AutomaticResetEvent. When I recieve the data back from the port (SerialPort::DataRecieved) I read the data off the port and call Set on the AutomaticResetEvent.

    I would expect that while the program is waiting on the AutomaticResetEvent, that no more VB6 events would be processed, but it appears as though they are.

    • Proposed as answer by CrazyGhost_Von Wednesday, October 17, 2012 10:36 AM
    Friday, October 5, 2012 11:59 AM
  • Hi Tyzack,

    As you stated, the waitone cannot wait for unmanaged thread.

    You need to wrap the COM method in a managed way.

    Have a nice day.


    Ghost,
    Call me ghost for short, Thanks
    To get the better answer, it should be a better question.

    Wednesday, October 17, 2012 10:36 AM
  • I'm trying to understand this line:

    As you stated, the waitone cannot wait for unmanaged thread.

    So that means that if I have an unmanaged caller into managed code at the manage code encounters a blocking wait, then unmanged caller will "detach" and continue execution?

    This doesn't make sense to  me.

    Also, in terms of the problem I am running into, how do you use the basic ::Enter/LeaveCriticalSection() windows calls in VB6?


    Wednesday, October 17, 2012 12:36 PM
  • Hi Tvzack,

    >>So that means that if I have an unmanaged caller into managed code at the manage code encounters a blocking wait, then unmanged caller will "detach" and continue execution?

    If you mean this:

    Sub managedMethod()
    unmanaged caller()
    SigalOne()
    End sub

    Yes. This is what I mean.


    Ghost,
    Call me ghost for short, Thanks
    To get the better answer, it should be a better question.

    Thursday, October 18, 2012 2:21 AM