c# - 包装异步方法

标签 c# asynchronous async-await

关于在 C# 中包装异步方法,我有一个奇怪的行为。

很难删除我的代码中有这种奇怪行为的部分,所以我做了一个测试项目来调查这种行为,这就是我所发现的。

我有一个测试类,它有一个异步方法,它只是另一个异步方法的包装器:(在我的原始代码中,它是一个包含 2 个对象的包装器类,它有包装器方法)

public class Test
{
    public async Task Delay()
    {
        await Task.Delay(1000);
    }
}

在我的测试程序中,我从异步事件处理程序运行以下代码:(在我的例子中是 Loaded 事件,因为我使用的是 WPF 窗口)

var test = new Test();
await Task.Delay(1000);
await test.Delay();
Task.Delay(1000).Wait();
test.Delay().Wait();

一切都很好,直到最后一行,它永远不会返回。

然后我尝试将测试类更改为以下内容,最后一行有效:

public class Test
{
    public Task Delay()
    {
        return Task.Delay(1000);
    }
}

我的问题是为什么第一种情况不起作用?

最佳答案

我详细描述了这种死锁情况 on my blogMSDN article 中.

默认情况下,当你await一个任务时,它会捕获当前的“上下文”(SynchronizationContext.Current,除非它是null,在这种情况下,它会捕获 TaskScheduler.Current)。当 async 方法恢复时,它会在该上下文中恢复。

在您的例子中,UI 上下文被捕获,并且您的 async 方法试图在延迟完成后在 UI 线程上恢复。但是,它无法恢复执行,因为 UI 线程被阻塞等待任务完成。

最好的解决方案是“一路”使用async;换句话说,不要阻塞 async 代码。

关于c# - 包装异步方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22016446/

相关文章:

c# - 这是 async-await 工作原理的正确图表吗?

c# - 真或假 : one should have Windows PC to program MonoGame games

c# - 未在 asp 按钮和 Bootstrap 下拉菜单中设置按钮对齐方式

c# - 混合交互行为给出 "points to immutable instance"错误

c# - 从另一个命令 Handle() 方法中调用命令

multithreading - Spring @Async 和 AbstractRoutingDataSource

c# - c#中线程模式的正确回调

asynchronous - polymer this.async vs Promise.then vs setTimeout

dart - 在Dart中,为什么要等待琐碎的(“empty”)StreamController流立即退出程序?

javascript - 将 async/await 回调传递给 sass (C++) 会随机崩溃