更新这个问题的目的是得到一个简单的答案Task.Run()和死锁.我非常理解不混合异步和同步的理论推理,我将它们铭记于心.我不是在向别人学习新事物; 我尽力做到这一点.有时候所有人都需要技术答案......
我有一个Dispose()需要调用异步方法的方法.由于95%的代码都是异步的,因此重构不是最佳选择.拥有IAsyncDisposable框架支持的(以及其他功能)将是理想的,但我们还没有.所以在同一时间,我需要找到一种可靠的方法从同步方法调用异步方法而不会发生死锁.
我宁愿不使用,ConfigureAwait(false)因为这使得责任分散在我的整个代码中,以便被调用者以某种方式行事,以防调用者是同步的.我宁愿在同步方法中做一些事情,因为它是一个不正常的bugger.
在阅读了Stephen Cleary关于另一个Task.Run()总是在线程池中调度甚至异步方法的问题的评论后,它让我思考.
在ASP.NET中的.NET 4.5或任何其他同步上下文中,将任务调度到当前线程/同一线程,如果我有一个异步方法:
private async Task MyAsyncMethod()
{
...
}
Run Code Online (Sandbox Code Playgroud)
我想从同步方法中调用它,我可以使用Task.Run()它Wait()来避免死锁,因为它将异步方法排队到线程池吗?
private void MySynchronousMethodLikeDisposeForExample()
{
// MyAsyncMethod will get queued to the thread pool
// so it shouldn't deadlock with the Wait() ??
Task.Run((Func<Task>)MyAsyncMethod).Wait();
}
Run Code Online (Sandbox Code Playgroud) 我用一个控制器和一个方法创建了一个简单的WebApi项目:
public static class DoIt
{
public static async Task<string> GetStrAsync(Uri uri)
{
using (var client = new HttpClient())
{
var str = await client.GetStringAsync(uri);
return str;
}
}
}
public class TaskRunResultController : ApiController
{
public string Get()
{
var task = Task.Run(() =>
DoIt.GetStrAsync(new Uri("http://google.com"))
);
var result = task.Result;
return result;
}
}
Run Code Online (Sandbox Code Playgroud)
我非常了解async/await和tasks; 斯蒂芬克莱里几乎虔诚地跟随他.只是存在.Result让我焦虑,我希望这会陷入僵局.我知道这Task.Run(...)很浪费,导致在等待异步DoIt()完成时占用一个线程.
问题是这不是死锁,而是让我心悸.
我看到一些答案,如/sf/answers/2282496401/,我也观察到SynchronizationContext.Currentlambda执行时为null.但是,我也有类似的问题,问为什么上面的代码会出现死锁,而且我发现死锁ConfigureAwait(false)是在使用(不捕获上下文)的情况下发生的.Result.
是什么赋予了?