runliuv

runliuv@cnblogs

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

 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。

--

 

posted on 2022-05-13 18:11  runliuv  阅读(1175)  评论(0编辑  收藏  举报