线程与消息队列

转载 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里面),那么应用程序中的其他所有线程或者其他所有窗口都共用主线程中的一个消息队列,当然也可以在线程中去写消息队列解析,但默认是都共用主线程的消息队列,然后解析中分发消息到各自窗体的消息映射函数

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

RIT+SHIQ构成了系统的硬件输入模型的核心  系统为每个线程维护一个消息队列,还维护一个全局的消息队列,称为系统硬件输入队列(SHIQ:SystemHanrwareInputQueue),用于存储...
  • JeanWaljean
  • JeanWaljean
  • 2010年10月27日 11:04
  • 4574

Windows消息响应机制之三:线程与消息队列

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

线程与消息队列

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

简单的线程消息队列实现

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

线程与消息队列

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

线程内使用SetTimer实现定时器

  • 2012年09月01日 23:20
  • 42KB
  • 下载

程序创建两个线程,第一个线程没有消息队列,主线程尝试给第一个

  • 2006年02月23日 09:05
  • 78KB
  • 下载

C++线程 消息队列

 进程是没有活力的,它只是一个静态的概念。为了让进程完成一些工作,进程必须至少占有一个线程,所以线程是描述进程内的执行,正是线程负责执行包含在进程的地址空间中的代码。实际上,单个进程可以包含几个...
  • sbz0409
  • sbz0409
  • 2016年07月26日 13:14
  • 831

深入浅出Win32多线程设计之MFC的多线程-线程与消息队列(经典)

3.线程与消息队列  在WIN32中,每一个线程都对应着一个消息队列。由于一个线程可以产生数个窗口,所以并不是每个窗口都对应着一个消息队列。下列几句话应该作为"定理"被记住:  "定理" 一  所有产...
  • zhangxinrun
  • zhangxinrun
  • 2010年08月05日 13:02
  • 3659

菜鸟来解释线程中的循环者Looper读取消息队列

安卓中的Looper使用就是用来给线程创建一个循环,类似while或for循环等。
  • dreamInTheWorld
  • dreamInTheWorld
  • 2015年01月19日 19:53
  • 1405
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:线程与消息队列
举报原因:
原因补充:

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