gpt4 book ai didi

c# - Async-Await 在预期死锁的地方没有死锁

转载 作者:行者123 更新时间:2023-11-30 14:26:50 25 4
gpt4 key购买 nike

众所周知,异步方法上的同步等待会导致死锁(参见,例如 Don't Block on Async Code)

我在 Windows 窗体应用程序中单击按钮的事件处理程序中有以下代码(即代码是通过安装的 UI SynchronizationContext 调用的)。

var client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Get, new Uri("http://www.google.com"));
Task<HttpResponseMessage> t = client.SendAsync(request);
t.Wait();
var response = t.Result;

我完全预料到代码会在单击按钮时发生死锁。然而,我实际看到的是同步等待——对话框暂时没有响应,然后照常接受事件。当我尝试同步等待 client 异步方法时,我总是看到死锁。但是,同步等待 library 异步方法(如 SendAsyncReadAsByteArrayAsync)似乎不会死锁。有人可以解释这种行为吗?

.NET 库中异步方法的实现不是在内部使用 await 语句,因此必须将延续编码回原始 SynchronizationContext 吗?

注意:如果我定义一个客户端方法,比如

public async Task<byte[]> wrapperMethod()
{
var client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Get, new Uri("http://www.google.com"));
var response = await client.SendAsync(request);
return await response.Content.ReadAsByteArrayAsync();
}

然后在按钮单击处理程序中说 byte[] byteArray = wrapperMethod().Result;,我确实遇到了死锁。

最佳答案

Don't implementations of async methods in .NET libraries use await statements internally?

一般不会。我还没有在 .NET 框架中看到在内部使用 async-await 的单个实现。它确实使用任务和延续,但不使用 asyncawait 关键字带来的编译器魔法。

使用 async-await 很简单,因为代码看起来是同步的,但实际上是异步运行的。但这种简单性在性能方面有非常小的代价。

对于大多数消费者来说,这个价格是值得的,但框架本身会尽可能地提高性能。

However, synchronously waiting on library async methods like SendAsync or ReadAsByteArrayAsync seems not to deadlock.

死锁是等待的默认行为的结果。当您等待一个未完成的任务时,SynchronizationContext 被捕获,当它完成时,继续在该 SynchronizationContext(如果它存在)上恢复。当没有async、await、captured SynchronizationContext等时,这种死锁是不会发生的。

HttpClient.SendAsync 专门使用 TaskCompletionSource 返回一个任务,而不将该方法标记为异步。你可以在github上的实现中看到here .

添加到现有异步等待类的大多数任务返回方法只是使用现有的异步 API(即 BeginXXX/EndXXX)构建任务。例如这是 TcpClient.ConnectAsync :

public Task ConnectAsync(IPAddress address, int port)
{
return Task.Factory.FromAsync(BeginConnect, EndConnect, address, port, null);
}

当您确实使用 async-await 时,尽管您在不需要捕获 SynchronizationContext 时通过使用 ConfigureAwait(false) 避免了死锁。建议库应始终使用它,除非需要上下文(例如 UI 库)。

关于c# - Async-Await 在预期死锁的地方没有死锁,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34470549/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com