线程与消息队列

转载 2012年03月30日 16:43:12

当一个线程第一次被创建时,系统假定线程不会用于任何与用户相关的任务。这样可以减少线程对系统资源的要求。但是,一旦该线程调用一个与图形用户界面有关的函数 (如检查它的消息队列或建立一个窗口 ),系统就会为该线程分配一些另外的资源,以便它能够执行与用户界面有关的任务。特别是,系统分配了一个THREADINFO结构,并将这个数据结构与线程联系起来。
THREADINFO结构体如下:

1.将消息发送到线程的消息队列
当线程有了与之联系的THREADINFO结构时,消息就有自己的消息队列集合。
    通过调用函数  BOOL  PostMesssage(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
    可以将消息放置在线程的登记消息队列中。
    当一个线程调用这个函数时,系统要确定是哪个线程建立了用 hwnd 参数标识的窗口。然后系统分配一块内存,将这个消息参数存储在这块内存中,并将这块内存增加到相应线程的登记消息队列中。并且该函数还设置QS_POSTMESSAGE唤醒位。函数 PostMesssage 在登记了消息后立即返回,调用该函数的线程不知道登记的消息是否被指定窗口的窗口过程所处理。
    还可通过调用函数  BOOL  PostThreadMesssage(DWORD dwThreadId, UINT uMsg, WPARAM wParam, LPARAM lParam)将消息放置在线程的登记消息队列中,同 PostMesssage 函数一样,该函数在向线程的队列登记消息后立即返回,调用该函数的线程不知道消息是否被处理。
    向线程的队列发送消息的函数还有 VOID PostQuitMesssage(int nExitCode) ;
该函数可以终止线程消息的循环,调用该函数类似于调用:PostThreadMesssage(GetCurrenThreadId( ), WM_QUIT, nExitCode, 0);但 PostQuitMesssage 并不实际登记一个消息到任何队列中。只是在内部,该函数设定 QS_QUIT 唤醒标志,并设置 THREADINFO 结构的 nExitCode 成员。

2.向窗口发送消息
将窗口消息直接发送给一个窗口过程可以使用函数 LRESULT SendMessage( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)窗口过程将处理这个消息,只有当消息被处理后,该函数才能返回。即具有同步的特性。
     该函数的工作机制:
2.1 如果调用该函数的线程向该线程所建立的窗口发送了一个消息,SendMessage就很简单:它只是调用指定窗口的窗口过程,将其作为一个子例程。当窗口过程完成对消息的处理时,它向 SendMessage 返回一个值。SendMessage 再将这个值返回给调用线程。
2.2当一个线程向其他线程所建立的窗口发送消息时,SendMessage就复杂很多(即使两个线程在同一个进程中也是如此)。windows 要求建立窗口的线程处理窗口的消息。所以当一个线程调用 SendMessage  向一个由其他进程所建立的窗口发送一个消息,也就是向其他线程发送消息,发送线程不可能处理该窗口消息,因为发送线程不是运行在接收进程的地址空间中,因此不能访问相应窗口的过程的代码和数据。(对于这个,我有点疑问:同一个进程的不同线程是运行在相同进程的地址空间中,它也采用这种机制,又作何解释呢?)实际上,发送线程要挂起,而由另外的线程处理消息。所以为了向其他线程建立的窗口发送一个窗口消息,系统必须执行一些复杂的动作。
     由于windows使用上述方法处理线程之间的发送消息,所以有可能造成线程挂起,严重的会出现死锁。
     利用一下4个函数可以编写保护性代码防护出现这种情况。
    1. LRESULT SendMessageTimeout( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT fuFlags, UINT uTimeout , PDWORD_PTR pdwResult);

2. BOOL SendMessageCallback( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam, SENDSYNCPROC pfnResultCallback,  ULONG_PTR dwData);

3. BOOL SendNotifyMessage( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);

  4.BOOL ReplyMessage( LRESULT lResult);
另外可以使用函数 BOOL InSendMessage( ) 判断是在处理线程间的消息发送,还是在处理线程内的消息发送

转自 http://www.cnblogs.com/yewsky/articles/1882730.html

几种消息队列:

        系统消息队列由Windows维护,线程消息队列则由每个GUI线程自己进行维护,为避免给non-GUI线程创建消息队列,所有线程产生时并没有消息队列,仅当线程第一次调用GDI函数时系统给线程创建一个消息队列。队列消息送到系统消息队列,然后到线程消息队列;非队列消息直接送给目的窗口过程。

  对于队列消息,最常见的是鼠标和键盘触发的消息,例如WM_MOUSERMOVE,WM_CHAR等消息,还有一些其它的消息,例如:WM_PAINT、WM_TIMER和WM_QUIT。当鼠标、键盘事件被触发后,相应的鼠标或键盘驱动程序就会把这些事件转换成相应的消息,然后输送到系统消息队列,由Windows系统去进行处理。Windows系统则在适当的时机,从系统消息队列中取出一个消息,根据前面我们所说的MSG消息结构确定消息是要被送往那个窗口,然后把取出的消息送往创建窗口的线程的相应队列,下面的事情就该由线程消息队列操心了,Windows开始忙自己的事情去了。线程看到自己的消息队列中有消息,就从队列中取出来,通过操作系统发送到合适的窗口过程去处理。

  一般来讲,系统总是将消息Post在消息队列的末尾。这样保证窗口以先进先出的顺序接受消息。然而,WM_PAINT是一个例外,同一个窗口的多个 WM_PAINT被合并成一个 WM_PAINT 消息, 合并所有的无效区域到一个无效区域。合并WM_PAIN的目的是为了减少刷新窗口的次数。

 

系统消息队列,就是windows系统自己控制的队列,编程人员管不了也不看不到
系统消息队列就是解析和分发每个消息到 哪一个应用程序当中

关键是 系统中运行的每一个应用程序,都有一个或只能有一个主线程,这个主线程里面就是一个死循环的解析消息队列(winmain里面),那么应用程序中的其他所有线程或者其他所有窗口都共用主线程中的一个消息队列,当然也可以在线程中去写消息队列解析,但默认是都共用主线程的消息队列,然后解析中分发消息到各自窗体的消息映射函数

相关文章推荐

多线程环境下不安全的消息队列存取---线程不同步会造成隐患

前面, 我们把消息队列存取都放在主线程中, 而在实际应用中, 很多时候, 存消息队列在主线程, 取消息队列在其他线程(如网络线程)。 下面, 我们将之前的程序改为多线程程序: #include #i...
  • stpeace
  • stpeace
  • 2014年12月06日 00:17
  • 2014

线程与消息队列

当一个线程第一次被创建时,系统假定线程不会用于任何与用户相关的任务。这样可以减少线程对系统资源的要求。但是,一旦该线程调用一个与图形用户界面有关的函数 ( 如检查它的消息队列或建立一个窗口 ),系统就...

java多线程消息队列的实现

1、定义一个队列缓存池:  //static修饰的成员变量和成员方法独立于该类的任何对象。也就是说,它不依赖类特定的实例,被类的所有实例共享。 private static ListQue...

简单的线程消息队列实现

1. 线程使用场景 (1)流水线方式。根据业务特点,将一个流程的处理分割成多个线程,形成流水线的处理方式。产生的结果:延长单一流程的处理时间,提高系统整体的吞吐能力。 (2)线程池方式。针对处理时...

消息队列 多线程 linux

这些天自己在学习消息队列的使用,经过几天的琢磨,总算了解了怎么使用了,趁现在思路清晰把自己的过程记录下来供自己以后查阅。 工作原理: 首先通过唯一标识创建消息队列,之后所有的线程都监听消息队列...

线程和消息队列的详解 【图】

RIT+SHIQ构成了系统的硬件输入模型的核心  系统为每个线程维护一个消息队列,还维护一个全局的消息队列,称为系统硬件输入队列(SHIQ:SystemHanrwareInputQueue),用于存储...

消息队列使用的四种场景介绍

消息队列中间件是分布式系统中重要的组件,主要解决应用耦合,异步消息,流量削锋等问题 实现高性能,高可用,可伸缩和最终一致性架构 使用较多的消息队列有ActiveMQ,RabbitMQ,ZeroMQ...
  • cws1214
  • cws1214
  • 2016年10月25日 14:50
  • 19922

windows 多线程 消息队列

Windows线程分为两种:Worker线程、GUI线程 worker线程:是指完全不牵扯到图形用户界面(GUI),纯粹做运算的线程。 GUI线程:负责建造窗口以及处理消息循环(拥有消...

线程的消息队列的代码资源

  • 2010年07月02日 09:15
  • 66KB
  • 下载

Android_子线程创建消息队列更新UI

  • 2015年12月07日 00:16
  • 2.53MB
  • 下载
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:线程与消息队列
举报原因:
原因补充:

(最多只允许输入30个字)