一种常用的GUI多线程编程情况之我见
在有GUI的多线程编程中,我们常常要求程序实现这样的一种功能。
GUI线程在接到用户某个输入后,生成一个工作线程,这个工作线程可能去查找一堆文件,可能去访问某个外设,可能去执行一段耗时的计算,现在我们期望GUI线程在生成工作线程后,能继续响应用户其它的操作,总之能继续工作。当工作线程做完相应的工作后,GUI线程企图知道工作线程已做完它的工作,GUI线程需要更新相应的界面呈现给用户工作线程的结果。
本人一直企图用教科书式的同步/互斥问题来解决这种工作模式,却发现无论是Windows OS的互斥量,事件,信号量都不能解决这种模式。
其原因很简单,无论对于互斥量,事件还是信号量,当GUI线程与工作线程通过这些对象进行同步/互斥时,它们都会进入一种停止/等待的状态。比如GUI线程创建工作线程,然后等待工作线程的信号量,这时操作系统会把GUI线程挂起,它根本就不能继续执行,这样的效果对于用户体验来说,多线程与单线程是没有分别的,因为工作线程在执行之时,GUI线程一直在等待,它不能相应其它的用户输入。
我本人的解决方法是用传递消息的方法在GUI线程与工作线程之间通信,用消息的方法来实现上面的需求。
GUI在创建工作线程后,并不去等待工作线程的任何信号量,而是继续执行,并自定义一个消息响应函数,当工作线程执行完相应工作后,需要向GUI线程发送这个自定义的消息,通知GUI线程它做完相应工作,GUI线程会在这个消息响应函数中做相应的工作,把工作线程的结果呈现给用户。
由于Windows的消息机制其实是主线程不断地轮询自己消息队列中的消息,然后调用相应的消息处理函数,所以我对上面需求的结论是:只有通过轮询,才能实现真正的异步回调模式,不止是windows,对于linux也是一样。如果在linux下写一个类似的,GUI线程在创建工作线程后并不挂起等待工作线程的状态,而是继续执行,等工作线程状态发生变化后由工作线程通知GUI线程,GUI线程再调用相应的处理函数。我在linux下是用信号来做的,通过GUI线程不停地去轮询自己的信号,来做相应的处理。
总而言之,要实现GUI线程在创建工作线程后并不挂起等待工作线程的状态,而是继续执行,等工作线程状态发生变化后由工作线程通知GUI线程,GUI线程再调用相应的处理函数这样一种功能,我认为轮询是必须的。因为OS不会也不大可能提供一种类似于中断处理的功能来实现线程之间的异步回调模式,想象一下,中断处理中,需要保存寄存器状态之类的操作,在用户设计的程序中,如果提供这样的功能,不单对效率有影响,对系统的破坏也很大,也增加了用户编程的复杂度。
由于本人水平有限,以上认识有可能有很大不足,希望大家能提出不同的见解,多多指教,本人在这谢谢大家,并开分相送!