从同步方法调用异步方法的最佳实践是什么?

Jon*_*s T 10 .net c# synchronization asynchronous async-await

我知道有些人会争论“为什么不将 SyncMethod() 设为异步方法呢?”。我们希望如此,但在现实世界中,有时出于向后兼容性的原因,我们必须保持 SyncMethod 的原样。

情况是这样的。下面的代码导致我们陷入僵局。

public void SyncMethod()
{
    var serviceResult = ProcessDataAsync().Result;
}

public await ServiceResult ProcessDataAsync()
{
    //Do other things
    await GetDataFromApiAsync();
}

private static HttpClient Client = new HttpClient(); 
public await ApiResult GetDataFromApiAsync()
{
    var response = await Client.GetAsync("http://api.com/getJson");
    dynamic obj = JsonConvert.DeserializeObject(await response.Content.ReadAsStringAsync());
    return obj;  
}
Run Code Online (Sandbox Code Playgroud)

选项 1:使用 Task.Run 并获取 task.Result。这解决了死锁问题,但它被迫在原始线程的同步上下文之外的新线程中运行。然而,在某些环境中这是非常不明智的:特别是 Web 应用程序。这是一个好的做法吗?

public void SyncMethod()
{
    Task<decimal> task = Task.Run<decimal>(async () => await ProcessDataAsync());
    var serviceResult = task.Result;
}
Run Code Online (Sandbox Code Playgroud)

Optoin 2:从 Sync 一直添加到最后一个异步方法。

public void SyncMethod()
{
    var serviceResult = GetDataFromApiAsync().ConfigureAwait(false).GetAwaiter().GetResult();;
}

public await ServiceResult ProcessDataAsync()
{
    //Do other things
    await GetDataFromApiAsync().ConfigureAwait(false);
}

private static HttpClient Client = new HttpClient(); 
public await ApiResult GetDataFromApiAsync()
{
    var response = await Client.GetAsync("http://api.com/getJson").ConfigureAwait(false);
    dynamic obj = JsonConvert.DeserializeObject(await response.Content.ReadAsStringAsync().ConfigureAwait(false));
    return obj;  
}
Run Code Online (Sandbox Code Playgroud)

选项 3Stephen Cleary答案

public void SyncMethod()
{
    var serviceResult = GetDataFromApiAsync().(sync: true).GetAwaiter().GetResult();
}
Run Code Online (Sandbox Code Playgroud)

所有这些解决方案都将解决死锁问题。我的问题是最佳实践是什么?

Ste*_*ary 8

最好的做法是什么?

没有最佳实践,原因如下:

每个 hack 在某些情况下有效,在其他情况下无效。没有一种技巧可以在所有情况下发挥作用。如果有一种在任何地方都有效的 hack,那么这将是每个人都会使用的,并且该 hack 将是最佳实践。但没有一种方法可以在任何地方发挥作用,因此不存在“最佳实践”。没有通用的解决方案

本文描述了各种技巧,并描述了每种技巧有效和无效的情况。