gpt4 book ai didi

c# - 异步方法上的 Task.Wait() 在本地工作,但不能通过其他方法工作

转载 作者:太空宇宙 更新时间:2023-11-03 20:51:10 25 4
gpt4 key购买 nike

我最近解决了尝试执行异步方法时遇到的问题。对我来说,这提出的问题多于解决的问题。简而言之,我很高兴它有效,但我不知道为什么会这样。

我试图运行 Microsoft Graph 客户端库的以下方法:

_graphServiceClient.Users[userPrincipalName].Request().GetAsync()

以下方法无效,因为它在使用 await 后挂起:

async Task<User> GetUser(string userPrincipalName)
{
User user = await _graphServiceClient.Users[userPrincipalName].Request().GetAsync();
return user;
}

以下方法也不起作用,因为它在执行 runTask.Wait() 后挂起:

User GetUser(string userPrincipalName)
{
return (User) GetResult(_graphServiceClient.Users[userPrincipalName].Request().GetAsync());
}

object GetResult<TResult>(Task<TResult> task)
{
using (task)
using (var runTask = Task.Run(async () => await task))
{
try
{
runTask.Wait();
return runTask.Result;
}
catch (AggregateException e)
{
throw e.InnerException ?? e;
}
}
}

这就是事情变得奇怪的地方,因为以下代码确实有效:

User GetUser(string userPrincipalName)
{
using (var task = Task.Run(async () => await _graphServiceClient.Users[userPrincipalName].Request().GetAsync()))
{
try
{
task.Wait();
return task.Result;
}
catch (AggregateException e)
{
throw e.InnerException ?? e;
}
}
}

虽然我意识到最后两种方法不被认为是最佳实践,但我完全不明白为什么第三种方法有效而第二种方法无效。在我看来,它们看起来几乎相同。

那么为什么第三种方法行得通,而第二种方法行不通呢?

最佳答案

首先,你需要了解how the deadlock happens . await 将(默认情况下)捕获“上下文”并将 resume executing the rest of the async method in that context .在 ASP.NET 经典案例中,这个“上下文”是一个请求上下文,一次只允许一个线程运行。在线程池线程上运行时,“上下文”是一个线程池上下文,它只是将 async 方法的其余部分排队到线程池中,它可以由任何线程池线程运行。

Blocking on asynchronous code is an antipattern .在具有单线程上下文(例如 ASP.NET Classic)的情况下,您可能会陷入死锁。在您的第一个死锁示例中,您在 ASP.NET Classic 上下文中调用了 GetUser,因此它的 await 将捕获该上下文。然后调用代码(也在 ASP.NET Classic 上下文中运行)将阻塞该任务。这会阻塞该上下文中的线程,从而阻止 GetUser 完成,因此您最终陷入死锁。

但即使您最终没有陷入死锁,您仍然会在一开始就放弃异步代码的所有好处。考虑“工作”示例,它属于另一个 antipattern (Task.Run on ASP.NET) .在这种情况下,Task.Run 导致 GetAsync 在线程池上下文中运行,因此在 ASP.NET Classic 上下文中阻塞线程不会死锁。然而,这也是一种反模式。

正确的解决方案是去async all the way .具体来说,您的 Controller 操作应该是 async 并在调用异步代码时使用 await 。假装 Wait()Result 不存在,您的代码会更快乐。

关于c# - 异步方法上的 Task.Wait() 在本地工作,但不能通过其他方法工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55161638/

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