使用PostThreadMessage在Win32线程间传递消息

PostThreadMessage可以用于线程之间的异步通讯,因为它不用等待调用者返回,这也许是线程通讯中最简单的一种方法了。

PostThreadMessage是一个Windows API函数。其功能是将一个消息放入(寄送)到指定线程消息队列里,不等待线程处理消息就返回。

原型:

BOOLPostThreadMessage( DWORDidThread, UINTMsg, WPARAMwParam, LPARAMIParam);

参数:

idThread   其消息将被寄送的线程的线程标识符。如果线程没有消息队列,此函数将失败。

返回值:

如果函数调用成功,返回非零值。如果函数调用失败,返回值是零。

如果idThread不是一个有效的线程标识符,或由idThread确定的线程没有消息队列,GetLastError返回ERROR_INVALID_THREAD_ID。

备注:

息将寄送到的线程必须创建消息队列,否则调用PostThreadMessage会失败。

用下列方法之一来处理这种情况:

方法1:调用PostThreadMessage,如果失败,则调用Sleep,再调用PostThreadMessage,反复执行,直到PostThreadMessage成功。

方法2:创建一个事件对象,再创建线程。在调用PostThreadMessage之前,用函数WaitForSingleObject来等待事件被设置为被告知状态。消息将寄送到的线程调用PeekMessage(&msg,NULL,WM_USER,WM_USER,PM_NOREMOVE)来强制系统创建消息队列。设置事件,表示线程已准备好接收寄送的消息。

消息将寄送到的线程通过调用GetMesssge或PeekMesssge来取得消息。返回的MSG结构中的hwnd成员为NULL。[1]

每一个消息队列将队列内的消息限制在10,000个。这个限制应该已经足够的大。如果一个程序超过这个限制,它应当被重新设计以避免占用如此多的系统资源。要修改消息个数的限制,应当修改注册表中对应的项。

注意:

1 . PostThreadMessage有时会失败,报1444错误(Invalid thread identifier. ),其实这不一定是线程不存在的原因,也有可能是线程不存在消息队列(message queue)造成的。

事实上,并不是每个thread都有message queue,那如何让thread具有呢?答案是,至少调用message相关的function一次,比如GetMessage,PeekMessage。

2. 如果是post动态分配的memory给另外一个thread, 要注意内存的正确释放。

3. PostThreadMessage不能够post WM_COPYDATE之类的同步消息,否则会报错。

4. 最好不要使用PostThreadMessage post message给一个窗口,使用PostMessage替代。

下面是我写的一个比较严整的例子,仅供参考。

#include <windows.h>

#include <cstdio>

#include <process.h>     //for _beginthreadex

#define MY_MSG WM_USER+100

const int MAX_INFO_SIZE = 20;

HANDLE hStartEvent; // thread start event

// thread function

unsigned __stdcall ThreadFunc(void *param)

{

printf("thread fun start\n");

MSG msg;

PeekMessage(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE);

if (!SetEvent(hStartEvent)) //set thread start event

{

printf("set start event failed,errno:%d\n",::GetLastError());

return 1;

}

while(true)

{

if (GetMessage(&msg,0,0,0)) //get msg from message queue

{

switch (msg.message)

{

case MY_MSG:

char * pInfo = (char *)msg.wParam;

printf("recv %s\n",pInfo);

delete[] pInfo;

break;

}

}

};

return 0;

}

int main()

{

HANDLE hThread;

unsigned nThreadID;

hStartEvent = ::CreateEvent(0, FALSE, FALSE,
0); //create thread start event

if
(hStartEvent == 0)

{

printf("create start event failed, errno:%d\n", ::GetLastError());

return 1;

}

//start thread

hThread = (HANDLE)_beginthreadex( NULL, 
0, 
&ThreadFunc,  NULL,  0, 
&nThreadID );

if (hThread == 0)

{

printf("start thread failed, errno:%d\n", ::GetLastError());

CloseHandle(hStartEvent);

return 1;

}

//wait thread start event to avoid PostThreadMessage return errno:1444

::WaitForSingleObject(hStartEvent, INFINITE);

CloseHandle(hStartEvent);

int count = 0;

while(true)

{

char* pInfo = new char[MAX_INFO_SIZE]; //create dynamic msg

sprintf(pInfo, "msg_%d",
++count);

if (!PostThreadMessage(nThreadID, MY_MSG, (WPARAM)pInfo,0))
//post thread msg

{

printf("post message failed, errno:%d\n", ::GetLastError());

delete[] pInfo;

}

::Sleep(1000);

}

CloseHandle(hThread);

return 0;

}



版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-03 21:21:16

使用PostThreadMessage在Win32线程间传递消息的相关文章

Android 使用handler实现线程间发送消息 (主线程 与 子线程之间)、(子线程 与 子线程之间)

keyword:Android 使用handler实现线程间发送消息 (主线程 与 子线程之间).(子线程 与 子线程之间) 相信大家平时都有使用到异步线程往主线程(UI线程)发送消息的情况. 本文主要研究Handler的消息发送. 包含主线程往子线程发送消息,子线程之间互相发送消息. 一.主线程向子线程发送消息. 实现过程比較简单: 主线程发送消息到异步线程.异步线程接收到消息后在再发送一条消息给主线程. 1. 初始化主线程的Handler,用来接收子线程的消息. 2. 启动异步线程.在异步线

详解 Qt 线程间共享数据(使用signal/slot传递数据,线程间传递信号会立刻返回,但也可通过connect改变)

使用共享内存.即使用一个两个线程都能够共享的变量(如全局变量),这样两个线程都能够访问和修改该变量,从而达到共享数据的目的. Qt 线程间共享数据是本文介绍的内容,多的不说,先来啃内容.Qt线程间共享数据主要有两种方式: 使用共享内存.即使用一个两个线程都能够共享的变量(如全局变量),这样两个线程都能够访问和修改该变量,从而达到共享数据的目的: 使用singal/slot机制,把数据从一个线程传递到另外一个线程. 第一种办法在各个编程语言都使用普遍,而第二种方式倒是QT的特有方式,下面主要学习一

iOS页面间传递消息之Delegate

在开发应用的过程中,我们需要频繁地在界面之间传递消息,有时候是传递信息,有时候是传递一个信号即可.在iOS开发中,有多种传递信息的方式.比如最简单的,如果我们要在从一个界面进入另一个界面时给新界面传递一些消息,只需要给新界面定义一些属性,然后在创建新界面的时候设置其属性值即可. 那么如果要从新界面反过来传递信息给原先的界面怎么做呢,怎么建立起一个沟通的桥梁呢?iOS也提供了很多种方式,比如Notification.Block.UserDefault等等.本文就讲解最常见也是最常用的一种方式,几乎

Delphi 线程间发送消息

线程B向线程A发送消息,SendMessage(线程A句柄, msg, wParam参数, lParam参数); 线程A重写WndProc(var Message: TMessage); 1 { 线程B发送消息 } 2 unit ThreadUnit; 3 4 interface 5 6 uses 7 Classes, ActiveX, businessService, Dialogs, Constant, Windows, Messages, SysUtils; 8 9 type 10 TUp

VC++多线程编程-线程间的通信和线程同步

引用:http://blog.csdn.net/zjc0888/article/details/7372258 线程间通讯 一般而言,应用程序中的一个次要线程总是为主线程执行特定的任务,这样,主线程和次要线程间必定有一个信息传递的渠道,也就是主线程和次要线程间要进行通信.这种线程间的通信不但是难以避免的,而且在多线程编程中也是复杂和频繁的,下面将进行说明. 使用全局变量进行通信 由于属于同一个进程的各个线程共享操作系统分配该进程的资源,故解决线程间通信最简单的一种方法是使用全局变量.对于标准类型

线程间的參数传递

在多线程编程中.经常须要从主线程传递參数给子线程或在主线程中获得子线程的计算结果, 若使用全局变量实现.必定须要对临界区保护,因此导致大量的切换工作造成效率的低下. 而利用进程间的參数传递能够解决这一问题. 两个方向的參数传递: 1.主线程向子线程传递參数: 通过函数 int pthread_create(pthread_t *thread, const pthread_attr_t *attr,void *(*start_routine) (void *), void *arg); 在创建线程

jmeter中线程之间传递参数

JMeter 变量作用域局限于所属线程.这样设计是经过深思熟虑的,目的是让测试线程能够独立运转.有时候用户可能需要在不同线程间(可能属于同一个线程组,也可能不属于同一个线程组)传递变量. 其中一种方法就是使用属性.属性为所有 JMeter 线程所共享,因此当某个线程设置一个属性后,其他线程就可以读取更新后的值. 如果存在大量数据需要在线程间传递,那么可以考虑使用文件.例如,测试人员可以在一个线程中使用监听器,保存响应到文件(Save Responses to a file )或者 BeanShe

线程间的参数传递

在多线程编程中,常常需要从主线程传递参数给子线程或在主线程中获得子线程的计算结果, 若使用全局变量实现,必然需要对临界区保护,因此导致大量的切换工作造成效率的低下: 而利用进程间的参数传递可以解决这一问题. 两个方向的参数传递: 1.主线程向子线程传递参数: 通过函数 int pthread_create(pthread_t *thread, const pthread_attr_t *attr,void *(*start_routine) (void *), void *arg); 在创建线程

Chromium线程模型、消息循环

多线程的麻烦 多线程编程是一件麻烦的事,相信很多人深有体会.执行顺序的不确定性,资源的并发访问一直困扰着众多程序员.解决多线程编程问题的方法分为两类:一是对并发访问的资源直接加锁:二是避免并发访问资源:Chromium采用第二种思想来设计多线程模型,通过在线程之间传递消息来实现跨进程通讯. 设计原则 Chromium希望尽量保持UI处于响应状态.为此遵循如下设计原则: 1 不在UI线程上执行任何阻塞I/O操作,以及其它耗时操作. 2 少用锁和线程安全对象 3 避免阻塞I/O线程 4 线程之间不要