C#.NET WinForm 多个子Task(子线程)嵌套 Task.WaitAll 阻塞UI线程 (界面)
情况:
DoIt()方法内,开了2个Task 执行任务,子任务中会更新UI。
DoIt() 是同步(UI线程)。
DoIt()部分代码:
var myTask = Task.Run(() => { DoIt2(lstBatch1, 1); }); Task.WaitAll(myTask); curMsg = NS() + " batch 2 "; InserLbxMsg(curMsg); myTask = Task.Run(() => { DoIt2(lstBatch2, 2); }); Task.WaitAll(myTask);
DoIt2 方法内会更新UI ,InvokeInserLbxMsg(curMsg); 。
/// <summary> /// BeginInvoke /// </summary> /// <param name="curMsg"></param> void InvokeInserLbxMsg(string curMsg) { if (this.InvokeRequired) { this.BeginInvoke(new MethodInvoker(() => { lbxMsg.Items.Insert(0, curMsg); })); } else { lbxMsg.Items.Insert(0, curMsg); } }
结果导致 DoIt2 更新UI失败,并阻塞了UI线程 。
解决方法:
DoIt 方法内2个Task.WaitAll,换成 ContinueWith:
var myTask = Task.Run(() => { DoIt2(lstBatch1, 1); }); myTask.ContinueWith(t => { DoIt2(lstBatch2, 2); InvokeInserLbxMsg("完成"); });
重点: UI线程的方法(同步),不要用Task.WaitAll。
--