UI线程和windows消息队列机制

    技术2023-03-28  19

          操作系统有一个系统消息队列,另外会为每一个UI线程创建一个消息队列。用户操作时,操作系统判断出当前操作是发生在哪个窗体组件对象,生成一条消息,先将其放在系统消息队列中,再分发到创建该组件对象的UI线程的消息队列中。UI线程中需要一个消息循环,不断从它自己的消息队列读取消息,并对取出的消息进行处理。

         

          (猜测,待考证)java中,swing或awt对象包含了一个消息循环。当从消息队列中取出一条消息后,根据消息中的源组件对象,找到该对象注册的监听器,然后调用监听器中的方法处理该消息。

     

     

     

    1、用户操作消息是怎样“跑”到UI线程的消息队列中的?

     

      我们知道,Windows同时可以运行多个进程,每个进程又拥有多个线程,其中有一些线程是UI线程,这些UI线程可能会创建不止一个窗体,那么问题发生了:

           用户在屏幕上某个位置按了一下鼠标,相关信息是怎样传给特定的UI线程,并最终由特定窗体的“窗体过程”负责处理?

           答案是操作系统负责完成消息的投寄工作。

     

           操作系统会监控计算机上的键盘和鼠标等输入设备,为每一个输入事件(由用户操作所引发,比如用户按了某个键)生成一个消息。根据事件发生时的情况(比如当前激活的窗体负责接收用户按键,而依据用户点击鼠标的坐标可以知道用户在哪个窗体区域内点击了鼠标),操作系统会确定出此消息应该发给哪个窗体对象。

     

           这些生成的消息会统一地先临时放置在一个“系统消息队列(system message queue)”中,然后,操作系统有一个专门的线程负责从这一队列中取出消息,根据消息的目标对象(就是窗体的句柄),将其移动到创建它的UI线程所对应的消息队列中。操作系统在创建进程和线程时,都同时记录了大量的控制信息(比如通过进程控制块和句柄表可以查找到进程所创建的所有线程和引用的核心对象),因此,根据窗体句柄来确定此消息应属于哪个UI线程对于操作系统来说是很简单的一件事。

     

           注意,每个UI线程都有一个消息队列,而不是每个窗体一个消息队列!

           那么,操作系统是不是会为每一个线程都创建一个消息队列呢?

           答案是:只有当一个线程调用Win32 API中的GDI(Graphics Device Interface)和User函数时,操作系统才会将其看成是一个UI线程,并为它创建一个消息队列。

          

    2、  简单地说,窗体和控件之所以能响应用户操作,关键在于负责创建它们的UI线程拥有一个“消息循环(Message Loop)”。这个消息循环由线程函数负责启动.

     

           需要注意的是,消息循环是由UI线程的线程函数启动的,操作系统不管这件事,它只管为UI线程创建消息队列。因此,如果某个UI线程的线程函数中没有定义消息循环,那么,它所拥有的窗体是无法正确绘制的。

     

    由此我们可以知道UI线程所完成的大致工作就是:

           UI线程启动一个消息循环,每次从本线程所对应的消息队列中取出一条消息,然后根据消息所包容的信息,将其转发给特定的窗体对象,此窗体对象所对应的“窗体过程”函数被调用以处理这些消息。

    最新回复(0)