我自定义了一个事件用来更新画面的进度条。
程序结构是子线程完成时触发事件,主线程(UI线程)订阅该事件做出响应。
现在的问题是,由于子线程完成的只是业务操作的一个步骤,所以我用join()
阻塞了UI线程,而事件更新进度条看起来又是在子线程里完成的,触发了事件委托的Invoke
的代码段,造成主线程等待子线程完成,而子线程又等待主线程完成的死锁状态
,请问这个要怎么解决?
-
事件类代码
public class ProgressChangeEventPublisher { public event EventHandler<ProgressChangeEventArgs> RaiseProgressChangeEvent; private void OnRaiseProgressChangeEvent(ProgressChangeEventArgs e) { RaiseProgressChangeEvent?.Invoke(null, e); } public void ProgressChange(ProgressChangeEventArgs e) { OnRaiseProgressChangeEvent(e); } }
-
事件触发
class subclass{ public ProgressChangeEventPublisher publisher = new ProgressChangeEventPublisher(); //子线程方法 private void threadmethod(object obj) { //用Semaphore对象控制线程并发数。 semahoro.WaitOne(); //激发事件 pub.ProgressChange( new ProgressChangeEventArgs()); semahoro.Release(); } //创建启动线程 void do() { List<Thread> tPool = new List<Thread>(); foreach (var src in paths) { Thread t = new Thread(new ParameterizedThreadStart(threadmethod)); t.Start(src); tPool.Add(t); } foreach (Thread t in tPool) { t.Join(); } } }
-
UI订阅代码
delegate void ChangeStatusBarHandler(int progress, string status); private void btn_Click(object sender, EventArgs e) { subclass cls = new subclass(); //实现事件订阅 cls.publisher.RaiseProgressChangeEvent += OnProgressChange; } //事件委托 void OnProgressChange(object sender, ProgressChangeEventArgs e) { if (e != null) { DoChangeStatusBar(e.percent, e.status_msg); } } void DoChangeStatusBar(int progress, string status) { if (InvokeRequired) { Invoke(new ChangeStatusBarHandler(DoChangeStatusBar), new object[] { e.percent, e.status_msg }); } else { tlPrgsBar.Value = progress; } }
使用task启动线程的代码
List<Task> tasks = new List<Task>(); foreach (var src in paths) { tasks.Add(Task.Factory.StartNew(threadRunParse,src)); } Task.WaitAll(tasks.ToArray());
Invoke改成BeginInvoke试试
既然这样,试试这个吧:
你问题的根源在于,你把主线程阻塞了,试问,主线程为什么要阻塞呢?
如果非要主线程等待执行结束后再执行一些事情,完全可以换种方式,比如做个进度完成的事件,主线程订阅后继续执行。