WinForm Task.Wait:为什么它会阻塞 UI?

问题描述 投票:0回答:1

我想这种事情一般不应该做,但我想了解为什么这段代码会阻塞 UI,而不是从 await taskMain 返回:

using System.Diagnostics;

namespace TasksTest
{
    public partial class FormMain : Form
    {
        public FormMain()
        {
            InitializeComponent();
        }

        private void buttonTest1_Click(object sender, EventArgs e)
        {
            try
            {
                DoTest1Async().Wait();
            }
            catch (Exception exc) 
            {
                MessageBox.Show(exc.ToString());
            }
        }

        private static async Task DoTest1Async()
        {
            Task taskMain = Task.Run(() => {
                Debug.WriteLine("Test #1 completed");
            });
            await taskMain;
        }
    }
}

如果我不使用 Wait() 而使用 wait ,它会完美地工作。我想知道是否有一种方法可以同步执行 DoTest1Async 而不会阻塞 UI。

-----已编辑----------

了解调用 Wait 方法会阻塞 UI 线程,并且不允许已完成的任务 taskMain 返回到 UI 线程上下文并恢复执行...为什么下一个代码替代方案不会以同样的方式阻塞 UI 线程? ?我仍然不明白为什么如果我在另一个线程中启动代码而 UI 线程在 thread.Join 中被阻止,那么 taskMain 可以返回,但它不能在简单的 Wait() 指令中返回。听起来很奇怪...也许 Wait 方法的实现需要修改...?

        private void buttonTest1_Click(object sender, EventArgs e)
        {
            Thread thread = new(() =>
            {
                try
                {
                    DoTest1Async().Wait();
                    Debug.WriteLine("Unblocked!!");
                }
                catch (Exception exc)
                {
                    MessageBox.Show(exc.ToString());
                }
            });
            thread.Start();
            thread.Join();
            Debug.WriteLine("Thread Finished!");
        }
.net task wait deadlock ui-thread
1个回答
0
投票

但我想了解为什么这段代码会阻止 UI

因为

Task.Wait
是一个阻塞操作:

Wait 是一种同步方法,它会导致调用线程等待,直到当前任务完成。如果当前任务尚未开始执行,Wait 方法会尝试从调度程序中删除该任务并在当前线程上内联执行它。如果它无法做到这一点,或者当前任务已经开始执行,它会阻塞调用线程,直到任务完成

未从等待任务Main返回

它返回,但后续的

Wait
调用会阻塞线程。

如果我不使用 Wait() 而使用 wait ,它会完美地工作。

如果它有效 - 使用它,

async
-
await
介绍的原因之一就是在类似这样的情况下使用。

我想知道是否有一种方法可以同步执行DoTest1Async而不阻塞UI。

不。根据定义。

另请阅读 Stephen Cleary 的不要阻止异步代码。阻塞不仅会冻结 UI 线程,还会导致死锁(看来您遇到了死锁)。

© www.soinside.com 2019 - 2024. All rights reserved.