c# - await 关键字阻塞主线程

标签 c# async-await

所以我有以下代码

private async void button1_Click(object sender, EventArgs e)
{
    await DoSomethingAsync();

    MessageBox.Show("Test");
}

private async Task DoSomethingAsync()
{
    for (int i = 0; i < 1000000000; i++)
    {
        int a = 5;
    }; // simulate job

    MessageBox.Show("DoSomethingAsync is done");

    await DoSomething2Async();
}

private async Task DoSomething2Async()
{
    for (int i = 0; i < 1000000000; i++)
    {
        int a = 5;
    } // simulate job

    MessageBox.Show("DoSomething2Async is done");
}

在显示两个 MessageBox 之前,主线程处于阻塞状态(我的意思是应用程序本身被卡住)。我的代码显然有问题,我不知道是什么。我以前从未使用过异步/等待。这是我的第一次尝试。

编辑:

实际上我想做的是开始异步执行 DoSomethingAsync 以便在单击按钮时 MessageBox.Show("Test"); 会执行,即使DoSomethingAsync 不完整。

最佳答案

我认为您误解了异步的含义。 并不代表该方法运行在另一个线程!!

异步方法同步运行直到第一个await,然后返回一个Task给调用者(除非它是async void,然后它返回没有什么)。当正在等待的任务完成时,执行在 await 之后恢复,通常在同一个线程上(如果它有一个 SynchronizationContext)。

在您的例子中,Thread.Sleep 在第一个等待之前,因此它是同步执行的,在控制返回给调用者之前。但即使它在 await 之后,它仍然会阻塞 UI 线程,除非您专门配置等待程序不捕获同步上下文(使用 ConfigureAwait(false) ).

Thread.Sleep 是一种阻塞方法。如果您想要异步等效项,请按照 Sriram Sakthivel 的回答中的建议使用 await Task.Delay(3000)。它会立即返回,并在 3 秒后恢复,不会阻塞 UI 线程。

异步与多线程有关是一种常见的误解。它可以是,但在许多情况下不是。一个新线程不会仅仅因为该方法是 async 而隐式生成;要产生一个新线程,它必须在某个时候显式完成。如果您特别希望该方法在不同的线程上运行,请使用 Task.Run

关于c# - await 关键字阻塞主线程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19813719/

相关文章:

javascript - 在等待 JavaScript 中的 promise 时到底发生了什么?

c# - ASP.NET:触发批处理作业

c# - ASP.NET Identity UserManager 缓存用户?

c# - 通过 C# 和德语 Umlaute (Ä,Ü,Ö,ä,ü,ö) 导入 DOS-CSV

c# - 如何在VS中创建sdk样式的.net框架项目?

c# 在 for 循环中等待

c# - 更新 ConcurrentDictionary 中的列表

c# - 如何编写不带 out 参数的异步方法?

javascript - 在 TypeScript 中使用 Promises 的异步函数的正确错误模式

javascript - 嵌套异步/等待函数