基本概念

在windows系统中,线程分为两种,分别是工作线程和UI线程:

工作线程:只处理逻辑的线程,例如:启动一个线程,(线程函数)用来做一个复杂的计算,计算完成之后,此线程就自动退出,这种线程称为工作线程
UI线程:Windows应用程序一般由窗口和控件组成,这也是应用程序与人交互的媒介,拥有窗口(控件)的线程称为UI线程;UI线程可以拥有一个UI线程的消息队列 一个进程可以拥有很多个工作线程,但是只能拥有一个UI线程,即一个进程若拥有UI线程,此UI线程一定是这个进程的主线程

消息与消息队列

  • Windows系统与人的交互,是一个产生消息 -->分发消息 -->处理消息 的过程,例如在某个窗口上点击鼠标,移动鼠标,按下键盘等等用户操作,都会产生一个消息(消息的结构体中会记录下,这个消息是在哪个窗口上产生的(窗口句柄),产生此消息时,鼠标所在位置,等一系列参数);具体的,可以查看Windows系统中,消息结构体的定义:
typedef struct tagMSG {
    HWND        hwnd;				//消息产生的窗口句柄
    UINT        message;			//消息类型
    WPARAM      wParam;				//wparam参数
    LPARAM      lParam;				//lparam参数
    DWORD       time;				//消息产生的时间
    POINT       pt;					//消息产生的坐标
#ifdef _MAC
    DWORD       lPrivate;
#endif
} MSG, *PMSG, NEAR *NPMSG, FAR *LPMSG;
  • Windows系统内部维护一个系统消息队列,windows会把所有应用程序产生的消息都存储在系统消息队列中
  • Window进程消息队列: 其实进程是没有消息队列的,消息队列是对线程而言,只不过一个进程中只能有一个UI线程,所以我们习惯性的将这个进程中的UI线程的消息队列,称为进程消息队列
  • Windows进程消息队列 == Widnow进程中,主(UI)线程的消息队列
  • Windows内部还有一个工作线程,这个工作线程,专门从 系统消息队列 中取出消息放到对应的 进程消息队列(根据进程的主(UI)线程有没有包含当前消息的窗口句柄,来判断消息是否属于当前进程)
  • 是不是每个进程都具有消息队列呢?
    回答是否定的。在Windows下,只有那些具备窗口(GUI用户接口界面)的进程,才会有消息队列,那些不具备GUI的进程是没有消息队列的。也就是说:操作系统在开启一个新的进程时,并没有为其创建消息队列,而是当进程第一次调用GDI函数后,并且进程持有窗口时,才持有消息队列

消息的处理

  • 上面介绍了,Windows中有一个工作线程,会从系统消息队列中取出消息,并根据这个消息内的标记(窗口句柄),将这个消息发送给产生此窗口的UI线程,(即把这个消息放到对应的UI线程(应用程序主线程)的消息队列)
  • 在UI线程内,一般有一个消息循环,类似于以下形式,我们可以看到,消息循环其实是一个while函数,这个函数不断地从此UI线程的消息队列中取出消息,并将消息派发给对应的窗口过程函数;正是因为有了这个While循环,我们的窗口才可以一直阻塞着不退出,一直与人进行交互
  • 那么什么是窗口过程函数呢
    实际上,每一个窗口、控件,都有一个属于自己的窗口过程函数(windows默认,或者自定义),用来处理在此窗口、控件上产生的消息;窗口过程函数的基本形式如下:我们可以看到,窗口过程函数,其实就是一个多分支函数罢了,它会根据消息类型的不同,来做不同的处理

最后附图,PostMessage和SendMessage的区别,PostMessage投递到消息队列中,而SendMessage直接投递给窗口过程函数,所以一个是异步(Post),一个是同步(Send)

ui线程 java_ui