zoukankan      html  css  js  c++  java
  • Why isn't there a SendThreadMessage function?

    Here's an interesting customer question:

    Windows has PostMessage and SendMessage. It also has PostThreadMessage but no SendThreadMessage.
    Why isn't there a SendThreadMessage function? Am I forced to simulate it with an event?

    What would this imaginary SendThreadMessage function do?

    Recall that SendMessage delivers the message directly to the window procedure;

    the message pump never sees it.

    The imaginary SendThreadMessage function would have to deliver the message directly to.... what?

    There is no "thread window procedure" to deliver it to.

    Okay, maybe you still intend to process the thread message in your message pump,

    but you want the caller of the imaginary SendThreadMessage function to wait until you've finished processing the message.

    But how does it know when you're finished?

    It can't wait for DispatchMessage to return, since DispatchMessage can't dispatch thread messages.

    (Where would it dispatch them to?)

    The processing of the thread message is completely under the control of the message pump.

    The window manager gives it a thread message, and as far as the window manager is concerned, that's the end of the story.

    You might say that the processing of the thread message is complete

    when somebody next calls GetMessage orPeekMessage,

    but there's no guarantee that the next call to a message-retrieval function will come from the message pump.

    Handling the thread message may result in a call to MessageBox, and as a modal function,

    it will have its own message loop, which will call GetMessage,

    resulting in your imaginary SendThreadMessage function deciding that message processing is complete when in fact it's still going on.

    What should you do instead?

    Just create a window and send it a message.

    The scenarios where you would want to use the PostThreadMessage function are very limited and specialized.

    Under normal circumstances, you should just send a regular window message.

    Thread messages (as generated by the PostThreadMessage function) do not go anywhere

    when passed to the DispatchMessage function.

    This is obvious if you think about it, because there is no window handle associated with a thread message. 

    DispatchMessage has no idea what to do with a message with no associated window.

    It has no choice but to throw the message away.

    This has dire consequences for threads which enter modal loops,

    which any thread with a window almost certainly will do at one time or another.

    Recall that the traditional modal loop looks like this:

    while (GetMessage(&msg, NULL, 0, 0)) {
     TranslateMessage(&msg);
     DispatchMessage(&msg);
    }

    If a thread message is returned by the GetMessage function,

    it will just fall through the TranslateMessage and DispatchMessage without any action being taken.

    Lost forever.

    Thread messages are generally to be avoided on threads that create windows, for this very reason.

    Of course, if you're going to create a window, why not use PostMessage instead,

    passing that window as the target of the posted message?

    Since there is now a window handle, the DispatchMessage function knows to give the message to your window procedure.

    Result: Message not lost.

    Why do messages posted by PostThreadMessage disappear?

    The only thread message you can meaningfully post to a thread displaying UI is WM_NULL,

    and even then, it's only because you want to wake up the message loop for some reason.

    A common problem I see is people who use PostThreadMessage to talk to a thread that is displaying UI

    and then wonder why the message never arrives.

    Oh, the message arrived all right. It arrived and then was thrown away.

    This is actually a repeat of an earlier entry with the title 

    Thread messages are eaten by modal loops,

    but I'm repeating it with a better subject line to help search engines.

    But since I'm here, I may as well augment the existing article.

    Obvious places where you have modal loops on a UI thread are functions that are explicitly modal l

    ike DialogBox orMessageBox or TrackPopupMenuEx(TPM_RETURNCMD) or DoDragDrop.

    But there are less obvious modal loops, like the modal loop that runs when you click on the caption bar and hold the button 

    or the modal loop that runs when COM is waiting for a cross-thread call to complete.

    And since you don't control those modal loops, when they call DispatchMessage,

    your thread message will simply be thrown away.

    If you need to communicate reliably with a thread that also displays UI,

    then create a hidden window and send or post messages to that window.

    I think this bit from the Platform SDK is relevant to the article:

    Message-Only Windows

    A message-only window enables you to send and receive messages.

    It is not visible, has no z-order, cannot be enumerated, and does not receive broadcast messages.

    The window simply dispatches messages.

    To create a message-only window, specify the HWND_MESSAGE constant

    or a handle to an existing message-only window in the hWndParent parameter of the CreateWindowEx function.

    You can also change an existing window to a message-only window by specifying HWND_MESSAGE

    in the hWndNewParent parameter of the SetParent function.

    To find message-only windows, specify HWND_MESSAGE in the hwndParent parameter of the FindWindowEx function.

    In addition, FindWindowEx searches message-only windows as well as top-level windows

    if both the hwndParent and hwndChildAfter parameters are NULL.

  • 相关阅读:
    FaceBook API
    CAP – Consistency, Availability, Partition Tolerance
    Hypothesis Testing
    MOSS 2007中如何添加VariationsLabelMenu来在不同语言的variation间切换?
    用Windows 2008 R2做工作机遇到的IE的安全问题
    如何使用Notepad++快速整理挤在一起的CallStack信息(将换行符作为被替换的内容)
    Managed Metadata Service介绍系列 之四
    MOSS 2007捞取ConfigDB中的数据, 得到内部名所对应的timer job的title及运行状况
    Log Parser分析IIS log的举例
    EventCache表太大, 怎么办?
  • 原文地址:https://www.cnblogs.com/shangdawei/p/4015350.html
Copyright © 2011-2022 走看看