包装异步方法

reS*_*Ned 2 c# asynchronous async-await

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

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

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

public class Test
{
    public async Task Delay()
    {
        await Task.Delay(1000);
    }
}
Run Code Online (Sandbox Code Playgroud)

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

var test = new Test();
await Task.Delay(1000);
await test.Delay();
Task.Delay(1000).Wait();
test.Delay().Wait();
Run Code Online (Sandbox Code Playgroud)

一切都很好,直到最后一行,永不回归.

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

public class Test
{
    public Task Delay()
    {
        return Task.Delay(1000);
    }
}
Run Code Online (Sandbox Code Playgroud)

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

Ste*_*ary 5

在我的博客MSDN文章中详细描述了这种死锁情况.

默认情况下,当您await执行任务时,它将捕获当前的"上下文"(SynchronizationContext.Current除非它是null,在这种情况下它会捕获TaskScheduler.Current).当async方法恢复时,它将在该上下文中恢复.

在您的情况下,捕获UI上下文,并且您的async方法尝试在延迟完成后在UI线程上继续.但是,它无法继续执行,因为UI线程被阻止等待任务完成.

最好的解决方案是使用async"一路"; 换句话说,不要阻止async代码.