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, , )) {
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.

Why isn't there a SendThreadMessage function?的更多相关文章

  1. 通过百度echarts实现数据图表展示功能

    现在我们在工作中,在开发中都会或多或少的用到图表统计数据显示给用户.通过图表可以很直观的,直接的将数据呈现出来.这里我就介绍说一下利用百度开源的echarts图表技术实现的具体功能. 1.对于不太理解 ...

  2. jsp中出现onclick函数提示Cannot return from outside a function or method

    在使用Myeclipse10部署完项目后,原先不出错的项目,会有红色的叉叉,JSP页面会提示onclick函数错误 Cannot return from outside a function or m ...

  3. JavaScript function函数种类

    本篇主要介绍普通函数.匿名函数.闭包函数 目录 1. 普通函数:介绍普通函数的特性:同名覆盖.arguments对象.默认返回值等. 2. 匿名函数:介绍匿名函数的特性:变量匿名函数.无名称匿名函数. ...

  4. 在ubuntu16.10 PHP测试连接MySQL中出现Call to undefined function: mysql_connect()

    1.问题: 测试php7.0 链接mysql数据库的时候发生错误: Fatal error: Uncaught Error: Call to undefined function mysqli_con ...

  5. jquery中的$(document).ready(function() {});

    当文档载入时执行function函数里的代码, 这部分代码主要声明,页面加载后 "监听事件" 的方法.例如: $(document).ready( $("a") ...

  6. Function.prototype.toString 的使用技巧

    Function.prototype.toString这个原型方法可以帮助你获得函数的源代码, 比如: function hello ( msg ){ console.log("hello& ...

  7. 转:ORA-15186: ASMLIB error function = [asm_open], error = [1], 2009-05-24 13:57:38

    转:ORA-15186: ASMLIB error function = [asm_open], error = [1], 2009-05-24 13:57:38http://space.itpub. ...

  8. [Xamarin] 透過Native Code呼叫 JavaScript function (转帖)

    今天我們來聊聊關於如何使用WebView 中的Javascript 來呼叫 Native Code 的部分 首先,你得先來看看這篇[Xamarin] 使用Webview 來做APP因為這篇文章至少講解 ...

  9. Oracle数据库自动备份SQL文本:Procedure存储过程,View视图,Function函数,Trigger触发器,Sequence序列号等

    功能:备份存储过程,视图,函数触发器,Sequence序列号等准备工作:--1.创建文件夹 :'E:/OracleBackUp/ProcBack';--文本存放的路径--2.执行:create or ...

随机推荐

  1. bootstrap-datetimepicker时间控件

    欢迎各种吐槽. 本人小前端,学习过程中,某日遇到做时间控件的需求,于是无休止的召唤了度娘,发现看不太懂.算是为自己做个笔记,也便于菜鸟级别的看的懂. 首先,我们看看点击选择时间的时候的展示页面吧 年  ...

  2. Arduino中的数据类型范围

    注意int不是4字节而仅仅是2字节!!! int: -32,768 ~ 32,767 (2字节) long: 4字节 http://www.arduino.cc/en/Reference/Int

  3. 把一个窗体嵌入到WinForm中进行显示,以CMD窗口为例

    1.添加引用 using System.Runtime.InteropServices; 2. 加入以下代码段 [DllImport("User32.dll ", EntryPoi ...

  4. STM32 UART 重映射

    在进行原理图设计的时候发现管脚的分配之间有冲突,需要对管脚进行重映射,在手册中了解到STM32 上有很多I/O口,也有很多的内置外设像:I2C,ADC,ISP,USART等 ,为了节省引出管脚,这些内 ...

  5. “iOS 推送通知”详解:从创建到设置到运行

    这是一篇编译的文章,内容均出自Parse.com的iOS开发教程,同时作者还提供了视频讲解.本文将带领开发者一步一步向着iOS推送通知的深处探寻,掌握如何配置iOS推送通知的奥义. 介绍一点点背景资料 ...

  6. 转——使用Axure制作App原型应该怎样设置尺寸?

    想用Axure设计一个 APP原型 放到真实的移动设备中演示,但不知道应该使用什么尺寸?若要解释清楚像素和分辨率需要的篇幅比较长,请大家参考百度百科.这里金乌直接给大家提供一个常用的移动设备尺寸列表, ...

  7. cocos2d-html5在cocos2d-x里面打包编译

    main.cpp打开USE_WIN32_CONSOLE输出 #include "main.h" #include "AppDelegate.h" #includ ...

  8. 第二百零六天 how can I 坚持

    今天爬了趟香山,第三次去了,要征服北京这大大小小的山. 要征服三山五岳,然后...罗娜.哈哈. 爬了趟山好累,人好多. 我的铜钱草. 洗刷睡觉,还是明天给鱼换水吧,好懒.

  9. 如何判断Socket连接失效

    http://cuisuqiang.iteye.com/blog/1453632 ——————————————————————————————————————————————————————————— ...

  10. ubuntu 安装ssh-server时出现错误:openssh-server: Depends: openssh-client (= 1:5.3p1-3ubuntu3) but 1:5.3p1-3ubuntu4 is to be installed

    错误如下: tiger@ubuntu:~/Desktop/work$ sudo apt-get install openssh-server [sudo] password for tiger: Re ...