最近正在做个项目,为了提高Form加载速度,将一些耗时较长的操作挪至一个新线程中执行;但是发现当子线程中通过Control.Invoke()方式操作Form控件,同时UI主线程在 Thread.Join()等待子线程执行完毕,这种方式实际上会导致UI主线程及子线程都处于阻塞等待状态,程序假死无法继续执行。
通过网上找资料发现,Invoke是一种UI层面同步操作方式;正式这种方式会导致2个线程死锁,具体原因如下:
1) 假设A为UI主线程,B为子线程
2) A 开启B线程后,A/B各自同步执行;
3) 当A到达Join()时,由于B尚未执行完成,A处于等待,线程处于阻塞状态;
4) B继续执行,当B执行到了Invoke操作时,它必须提交消息给UI主线程A,由它去执行实际操作;而此时由于A处于阻塞状态它无法
接收到消息或者接收到消息也无法去执行;而由于Invoke是一种同步执行机制,亦即在Invoke操作在未执行完成前,B不能继续往下
走,也就是B也将进入阻塞状态;于是死锁就出现了,整个程序无法运行。
要解决这个问题,关键就是把UI同步操作方式Invoke改为异步操作方式BeginInvoke就可以了;这样B在启动BeginInvoke后并不需要等待A执行完成就可以继续执行直至完毕。当B结束后,A的Join操作将被唤醒,在A执行完后再执行BeginInvoke操(此时的执行顺序很值得注意)。
大家可以参考如下转载文章:http://www.cnblogs.com/Rustle/articles/11301.aspx
http://www.cnblogs.com/c2303191/articles/826571.html
(一)Control的Invoke和BeginInvoke
我们要基于以下认识:
(1)Control的Invoke和BeginInvoke与Delega