C# 从同步操作方法调用异步方法:Task.Run或ConfigureAwaits(false)
我可以在控制器的同步操作方法中使用:ConfigureAwaits(false)对任务或使用任务。运行来防止结果调用异步任务的死锁。在这两种情况下,异步方法都将在线程池中的线程上完成。控制器源:C# 从同步操作方法调用异步方法:Task.Run或ConfigureAwaits(false),c#,asynchronous,task,deadlock,C#,Asynchronous,Task,Deadlock,我可以在控制器的同步操作方法中使用:ConfigureAwaits(false)对任务或使用任务。运行来防止结果调用异步任务的死锁。在这两种情况下,异步方法都将在线程池中的线程上完成。控制器源: public class TestController : Controller { /// <summary> /// Thread from threadpool will be used to finish async method. /// </summ
public class TestController : Controller
{
/// <summary>
/// Thread from threadpool will be used to finish async method.
/// </summary>
public string TaskRun()
{
return Task.Run(GetStatus).Result + " <br/> " +
Thread.CurrentThread.ManagedThreadId + " - " +
Thread.CurrentThread.IsThreadPoolThread;
}
/// <summary>
/// After completion it will try to finish async method in original thread used to work for httprequest.
/// </summary>
public string Deadlock()
{
return GetStatus().Result;
}
/// <summary>
/// Thread from threadpool will be used to finish async method.
/// </summary>
public string AwaitsFalse()
{
return GetStatusAwaitsFalse().Result + " <br/> " +
Thread.CurrentThread.ManagedThreadId + " - " +
Thread.CurrentThread.IsThreadPoolThread;
}
public async Task<string> PureAsync()
{
return await GetStatus() + " <br/> " +
Thread.CurrentThread.ManagedThreadId + " - " +
Thread.CurrentThread.IsThreadPoolThread;
}
public static async Task<string> GetStatusAwaitsFalse()
{
using (var httpClient = new HttpClient())
{
var response = await httpClient.GetAsync("http://www.google.com")
.ConfigureAwait(false);
return response.StatusCode + " - " +
Thread.CurrentThread.ManagedThreadId + " - " +
Thread.CurrentThread.IsThreadPoolThread;
}
}
public static async Task<string> GetStatus()
{
using (var httpClient = new HttpClient())
{
var response = await httpClient.GetAsync("http://www.google.com");
return response.StatusCode + " - " +
Thread.CurrentThread.ManagedThreadId + " - " +
Thread.CurrentThread.IsThreadPoolThread;
}
}
}
/test/waitsfalse的输出相同。有什么不同吗?异步同步没有通用的解决方案,只有各种各样的反模式存在不同的问题。有关详细信息,请参阅我的
ConfigureAwait(false)
的问题是,它必须在调用方法的传递闭包中的每个await
的任何地方应用。错过一次很容易,然后你就会陷入僵局。例如,上次我检查时,HttpClient.GetAsync
的一个移动平台版本缺少一个。即使您(以及您所有的依赖项)完美地完成了这项工作,但随着时间的推移,维护它也同样困难
Task.Run
的问题在于它在线程池线程上运行代码。(显然)。对于可以在线程池线程上运行的代码来说,这很好,但并非所有代码都是这样。它的效率也较低,而且(如果过度使用)会导致ASP.NET上的可伸缩性问题
另外,如果您坚持阻塞,请使用
GetAwaiter().GetResult()
而不是Result
,因为Result
会将异常包装在一个aggregateeexception
中,退一步:为什么您首先要使用同步操作来调用异步方法?@CharlesMager,因为它很有趣。我理解它是如何使用“纯异步”方法的。现在我试图找出不好的情况,以便更深入地理解它。此外,根据异步等待的最佳实践,您应该“在可能的情况下使用ConfigureAwait(false)”()。它可以防止在UI线程上调用结果时出现死锁。所以对我来说很有趣:我能用另一种方式做同样的事情吗?
OK - 12 - True
6 - True