C# 从同步操作方法调用异步方法:Task.Run或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

我可以在控制器的同步操作方法中使用:ConfigureAwaits(false)对任务或使用任务。运行来防止结果调用异步任务的死锁。在这两种情况下,异步方法都将在线程池中的线程上完成。控制器源:

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