Visual C++ Developer Center > Visual C++ Forums > Visual C++ General > Parented windows owned by different threads
Ask a questionAsk a question
 

QuestionParented windows owned by different threads

  • Friday, October 30, 2009 10:21 AMBidus Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     

    I have 2 threads in my Win32 application.

    Each thread creates a window.

    The window created by the second thread is parented to the window created by the first thread.

     

    What are the known problems of this «architecture» ?

    • Edited byBidus Friday, October 30, 2009 10:34 AMmistake
    •  

All Replies

  • Friday, October 30, 2009 10:24 AMBidus Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     
    Here are some details to help you precise your answers :

    Subject of the application:

    The Main thread M of my application uses a rendering engine that works in a separate thread T.

    M builds a scene to render.

    T computes frames to display, thanks to the scene content built by M.

    Then T displays resultant frames in its window.

     

    Prerequisites:

    M contains the UI message-pump.

    A frame window is created by M.

    A child window(where scene is displayed) of this frame is created by T (Since DX Device is built on this thread, rendering must be done in a window of this thread).

     

    Already solved:

    In the first iteration of my application, message-pump thread was sometimes locked, since I had written, in M, loops waiting for rendering engine to process frames.

    As soon as messages were sent from child window (owned by T) to parent window (owned by M), deadlocks were systematic.

    I have now got rid of these locks, since there are not any loops waiting for rendering engine anymore.

     

    The questions:

    Parented windows owned by different threads is known as leading to fatal deadlocks. Why ?

    Although message-pump can not be locked anymore, must I worry of deadlock ?

    Do you know an alternative to this architecture, to use a multithreaded rendering engine ?

  • Friday, October 30, 2009 12:18 PMBelloc Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     
    Suppose you click on the window owned by T, while T is running. Windows will send the parent a WM_PARENTNOTIFY message. I believe this will cause a deadlock. In summary, any message sent from the child to the parent will cause a deadlock. The reverse is also true.
  • Friday, October 30, 2009 2:06 PMBidus Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     

    If WM_PARENTNOTIFY message is sent to the parent, T is locked while this message has not been treated by the parent window.
    But the message is effectively treated as an unqueued messages of the thread M, during the next execution of GetMessage or PeekMessage(*). In this way, when system suspends thread T and resumes thread M, message-pump of M is processed, calling a PeekMessage, which treats the unqueud message.
    When it is time for T to be resumed, WM_PARENTNOTIFY has been treated, and T is not locked anymore.
    I have traced the case with the message WM_SETCURSOR. It seems to behave like this, and I have not got any deadlock.

    If I make a mistake in my reasoning (or if you can complete it), thank you to explain it to me.


    (*) In http://msdn.microsoft.com/en-us/library/ms644950, you can read : "Messages sent between threads are processed only when the receiving thread executes message retrieval code. The sending thread is blocked until the receiving thread processes the message."

  • Friday, October 30, 2009 2:13 PMBelloc Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     
    WM_PARENTNOTIFY is not posted. It is sent to the window proc. So, there is no queue involved in this case. What you have is : running thread T is sending a message to thread M, and waits for that message to be processed. That's the deadlock.
  • Friday, October 30, 2009 2:46 PMBidus Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     
    If the windows have been created by the same thread, a sent message involves the call of the window proc, I agree with you.

    But, if the windows have been created on different threads, a sent message is stored by the system as an unqueued message (I do not mean that a queue is involved in this case).

    In http://msdn.microsoft.com/en-us/library/ms644943(VS.85).aspx, you can read :

    "During this [PeekMessage] call, the system delivers pending, nonqueued messages, that is, messages sent to windows owned by the calling thread [...]. [...], messages are processed in the following order:

    • Sent messages
    • Posted messages
    • [...]" 
  • Friday, October 30, 2009 2:58 PMBelloc Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     
    When a message is sent to a window it is sent directly to the windows processing function. I don't understang why do you mention PeekMessage(), as the sent message (WM_PARENTNOTIFY) doesn't pass through the message loop !

    Actually a posted message like WM_SETCURSOR, you mentined above, doesn't cause a deadlock, simply because this message is posted, not sent.
  • Friday, October 30, 2009 3:42 PMBidus Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     
    I do not mention PeekMessage for what it does on posted messages. I mention it for the stuff it seems to do on sent messages. Why would PeekMessage documentation (my last post link) mention sent messages, if all sent messages were treated directly by windowProc ?
    (I think that sent messages from another thread are treated in another way, and code stepping seems to show me that this other way uses sent mesages handling done inside PeekMessage).

    Otherwise http://msdn.microsoft.com/en-us/library/ms648382(VS.85).aspx confirms that WM_SETCURSOR is a sent message, not a posted one.
  • Friday, October 30, 2009 3:59 PMBelloc Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     
    WM_SETCURSOR is posted

    You can verify this with InSendMessageEx() function
  • Friday, October 30, 2009 4:00 PMBelloc Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     
    PeekMessage() doesn't deal with sent messages
  • Friday, October 30, 2009 4:15 PMBidus Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     
    What does "The PeekMessage function dispatches incoming sent messages" mean ?
  • Friday, October 30, 2009 4:34 PMBelloc Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     
    Notwithstanding the fact that english is not my native language, I'd dare to say this is just a misword.
    • Edited byBelloc Friday, October 30, 2009 4:38 PMtypo
    •  
  • Friday, October 30, 2009 4:46 PMBrian MuthMVPUsers MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     
    Imagine designing an application where one thread looks after all the windows (called the GUI thread), and one or more worker threads are launched to handle chunks of the business logic. It's very straight forward, conventional, and from experience, simply works. Contrast this to marching into No-Man's Land with unknown pitfalls at every turn, and even when things seem to be working, the unsettling feeling that something unanticipated might happen once the application goes into production.

    I suggest chucking your design.
  • Friday, October 30, 2009 5:11 PMBidus Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     
    To answer Belloc :

    At the bottom of http://msdn.microsoft.com/en-us/library/ms644936(VS.85).aspx, you can read :

    "Sent Messages Are not Retrieved by GetMessage       
    It is worth noting that Sent Messages are processed within GetMessage itself and are not retrieved by GetMessage. "
  • Friday, October 30, 2009 5:23 PMBelloc Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     

    Who is xMartian ? Anybody can place any comment there.

  • Saturday, October 31, 2009 1:03 PMBelloc Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     
    Bidus:

    I've been doing some research since our discussion yesterday and I came to realize that you may be right, on what you were trying to tell me, regarding the GetMesage() and PeekMessage() functions dispatching nonqueued messages.

    From the GetMessage() definition :

    The GetMessage function retrieves a message from the calling thread's message queue. The function dispatches incoming sent messages until a posted message is available for retrieval.

    From PeekMessage() :

    The PeekMessage function dispatches incoming sent messages, checks the thread message queue for a posted message, and retrieves the message (if any exist).

    I'm still trying to understand how this is done, especially when a SendMessage() is called from another thread, but so far this is not totally clear to me yet.

    I've found some other links that might be of your interest :

    http://blogs.msdn.com/oldnewthing/archive/2004/06/08/150929.aspx

    http://www.eggheadcafe.com/software/aspnet/33029067/how-does-peekmessage-real.aspx

    Maybe this link has the answer, but for me at least, it misses some important details :

    http://social.msdn.microsoft.com/forums/en-US/windowssdk/thread/e6bf8976-3510-4b14-8ac0-d70610c0a0e4/


    But anyway, assuming that is the case, a deadlock is still possible. Let's take the example I gave you with the WM_PARENTNOTIFY message sent to the parent when the child window is clicked with the mouse. Thread T will stop executing, waiting for the SendMessage(WM_PARENTNOTIFY) to return from thread M. If this message causes Windows to send a message back to the child, thread M will stop executing waiting the return from thread T. Deadlock. 

    • Edited byBelloc Saturday, October 31, 2009 10:01 PMtypo
    •  
  • Tuesday, November 03, 2009 5:11 PMBidus Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     

    From the first link you gave me, I can read: "If one thread T1 send a message to a window that belongs to another thread T2, the sending thread T1 is put to sleep until the receiving thread replies to the message. But if somebody else sends a message to thread T1, thread T1 is woken to process the message, then is returned to sleep."
    In this way, the deadlock you describe at the end of your post does not appear so evident to me anymore, does it ?

    I have now another question : How does Windows do to return the result of the WindowProc executed on the second thread, when it awakes  the first thread ? Any idea ?

    Unfortunately, the suggestion box of the great "The old new thing" blog has been temporarily closed, and I cannot post the question of this current thread on this blog...

    For our information, here are some other interesting links I have noticed, reading yours :
    http://blogs.msdn.com/oldnewthing/archive/2004/11/19/266664.aspx
    http://msdn.microsoft.com/en-us/magazine/cc301431.aspx