【发布时间】:2017-03-12 18:41:48
【问题描述】:
我可以防止 Result 在控制器的同步操作方法中调用异步任务的死锁:ConfigureAwaits(false) on Task 或使用 Task.Run 。在这两种情况下,异步方法都将在线程池中的线程上完成。控制器来源:
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/taskrun 的输出(最后两个 int 值是 ManagedThreadId 和 IsThreadPoolThread):
OK - 12 - True
6 - True
/test/awaitsfalse 的输出是相同的。有什么区别吗?
【问题讨论】:
-
退后一步:为什么你首先使用同步操作来调用异步方法?
-
@CharlesMager 因为它很有趣。我了解它如何与“纯异步”方法一起使用。现在我正在尝试找出不良案例以更深入地了解它。
-
此外,根据异步等待的最佳实践,您应该“尽可能使用 ConfigureAwait(false)”(msdn.microsoft.com/en-us/magazine/jj991977.aspx)。它可以防止在 UI 线程上调用 Result 时出现死锁。所以这对我来说很有趣:我可以用另一种方式做同样的事情吗?
标签: c# asynchronous task deadlock