某项目里使用了soui的通知中心的SRUNONUISYNC实现ui和后台线程之间的同步!发现窗口关闭时后台线程小概率出现随机join后死锁现象!由于这个现象出现的几率很小十分难调试,在我本机甚至无法复现,只得研究代码过程!好在代码量不大,排除几处可能得情况,最后锁定在SRUNONUISYNC上!因为它的原理就是使用SendMessage来实现同步!那么为什么它会发生死锁呢?首先这个关闭动作发生在一个消息处理过程中即鼠标点击事件,这个时候如果SendMessage的情况则分两种,一是来自本ui线程,这个时候它是直接调用窗口过程的这个时候自然没问题,但是这里明显不是来自本线程这个时候SendMessage过来的消息只能进入消息队列等待后面的消息分发而这个时候SendMessage的线程因为SendMessage没得到处理而处于阻塞状态,而另一边ui线程因为等待后台线程join退出也处于阻塞状态造成死锁!找到问题就好处理了,微软似乎也意识到这个坑给我们提供了MsgWaitForMultipleObjects来处理这种情况!此外soui提供的SRUNONUI它是使用postmessage来实现的则无此问题!此外改造sendmessagetimeout来替代sendmessage也是可以的,这两个方法会有另一个问题post方式因为只是把它放进消息队列这个时候如果要操作ui就一定要小心书写代码,因为它执行的时候可能这个ui已经不在了!此外在MsgWaitForMultipleObjects分发消息时还有一个坑点,如果这个消息处理中被阻塞DispatchMessage将会阻塞进而再次引发死锁!
由sendmessage引发的血案
最新推荐文章于 2023-08-02 15:11:05 发布