工作线程界面输出时防止死锁的讨论
工作线程界面输出时防止死锁的讨论
背景:
这是一种很常见的情况,工作线程有一些或多或少的信息需要反映在界面上,比如在进度条上反映进度,在列表中显示并不断的刷新结果等等。这类操作本质上是向控件发消息sendmessage()。
问题:
如果主线程需要让工作线程停下来,或者也需要操作同一个控件的话,这就产生了一个同步问题。分两种情况
1、 主线程等待工作线程停止,如果这时工作线程向控件发消息(sendmessage),两个线程就会死锁;
2、 主线程和工作线程都需要操作控件,这两个线程必须互斥的操作这个控件,否则可能引起控件状态的不一致。如果简单的用临界区来互斥也可能会发生死锁。
(注意!!!这里的“操作”指的是一系列相互关联的操作,比如对列表进行多个项的更新,排序等等。单个的操作不在讨论之列,消息机制可以保证互斥)
一般的解决方案:
1、对于停止工作线程的情况:设置一个标志量,主线程在进入等待前先设置这个标志为true,工作线程在进行界面操作前先判断这个标志,如果标志为true就不对界面进行操作。
2、对于互斥操作控件的情况:设置一个标志,在线程A进行控件操作前设置为true,结束一系列的操作后设置为false;在另外一线程B中如果要操作控件就判断这边的标志,如果为true就进行等待,等待时使用 :PeekMessage() ::TranslateMessage); ::DispatchMessage();
来防止死锁。直到标志为false才进行操作。当然线程B在操作前后也要设置自己的标志量。
我提的问题:
以上的解决方法在实际运行中似乎没有出现过问题,但是根本经不起严格的分析。
依靠标志量的方法是不可靠的。对于1再密集的判断都不能保证:判断语句之后,sendmessage语句之前主线程不陷入等待。对于2不能保证线程B在设置自己的标志前,线程A判断B的标志为false从而两个线程对控件进行的复杂操作“混杂”起来。
这些标志会使程序变得复杂而不能真正的解决问题。
大家都来说说你们用什么方法解决这个问题呢,最好是简单又可靠