C# httpclient是否异步/等待

C# httpclient是否异步/等待,c#,async-await,dotnet-httpclient,C#,Async Await,Dotnet Httpclient,我使用一个httpclient实例向RESTWebAPI发送多个请求以获取数据。下面是我的代码的样子: 首先,我有一个控制层,它调用数据层来获取数据 public class ControlLayer { protected DataLayer dal; //constructors here public int getInfo1(int param) { int ret = this.dal.getInfo1(param); ret

我使用一个httpclient实例向RESTWebAPI发送多个请求以获取数据。下面是我的代码的样子:

首先,我有一个控制层,它调用数据层来获取数据

public class ControlLayer
{
    protected DataLayer dal;

    //constructors here

    public int getInfo1(int param)
    {
      int ret = this.dal.getInfo1(param);
      return ret;
    }

    public int getInfo2(int param)
    {
      int ret = this.dal.getInfo2(param);
      return ret;
    }
}
然后是调用webAPI的数据层,看起来是这样的。为了简单起见,我直接使用.result

public class DataLayer
{
    HttpClient client = new HttpClient();
    string url = "";

    public int getInfo1(int param1)
    {
      int ret=0;
      HttpResponseMessage response = client.GetAsync(url).Result;
      //.... do some work, get the value for ret

      return ret;
    }

    public int getInfo2(int param1)
    {
      int ret = 0;
      HttpResponseMessage response = client.GetAsync(url).Result;
      //.... do some work, get the value for ret

      return ret;
    }
}
我的问题是,我看到一些教程说我们应该避免使用.result,因为它可能会导致死锁。我不确定在我的情况下,我需要使用 异步/等待?如果我确实需要,我知道我应该一直异步,但我确实希望我的controlLayer是同步的,因为我有另一个层调用 controlLayer的函数,我不希望所有层的函数都是异步的,结果是任务,这是一种同步超过异步的情况吗?我想念你吗
某物如有任何建议,我们将不胜感激。谢谢

如果您的代码是异步的,您只需要使用
async
wait
——例如,如果它同时发送多个请求,则在发送请求后执行工作,而不只是阻塞直到响应到达

暂时忽略死锁问题—如果您的代码只是同步的,也就是说:每次发送请求时,您只需等待响应,然后再执行其他操作,您不需要使用
wait
,也可以使用
Result
。请参见类似的辩论。或者,您可以使用同步API(如注释和其他答案中建议的
WebClient

至于
Result
相关的死锁,我建议您阅读,以便更好地了解发生了什么以及原因。如果您正在编写一个简单的控制台应用程序,您实际上不需要担心它(正确的处理方法是只使用主方法非异步,并在那里使用
Result
Wait

我确实希望我的controlLayer是同步的,因为我有其他层调用controlLayer的函数,我不希望所有层的函数都是异步的,结果是任务

我建议你重新考虑一下。web请求基本上是一种异步操作,因此我建议您将“控制层”公开为异步API,并允许
async
在代码库的各个层中“增长”


然而,如果您真的想要一个同步API,那么您应该只调用同步API。例如,使用
WebClient
而不是
HttpClient
。不要调用
Result
来用同步API包装异步API。

如果您不希望代码是异步的(是好是坏-您的个人调用),那么不要进行异步调用。不确定您有什么问题…谢谢您的快速回复,您是否建议直接使用.result函数?这会导致死锁吗?@AlexeiLevenkov HttpClient有一个异步API,因此您必须使用
Result
wait
结果。
HttpClient
不是唯一的API。。。如果您更喜欢同步代码
WebRequest
可能是另一种选择。。。但这完全取决于作者是否能够控制代码的使用位置(请参阅sinelaw答案+1中的链接)-如果是控制台应用程序,同步等待异步方法是可以的,否则必须小心避免死锁。@AlexeiLevenkov HttpClient可能不是唯一的选择,但我仍然觉得它足够好,我不想使用其他方法。如何使HttpClient像WebClient一样(同步)工作,而不存在死锁的风险?(不过,在请求完成之前,我仍然希望阻止UI线程)。谢谢!在我的例子中,我有一个clientLayer发送请求参数,可以同时发送,在我得到响应后,我会将结果发送给clientLayer,所以我想我确实需要异步并等待,但是你知道如何处理异步同步吗?@Vicky,阅读这篇文章-他们推荐的“最佳实践”之一是“始终异步”-让所有代码始终异步到可能的最高级别,并使用Result and Wait()。@LenielMacaferi:我不同意这个答案。在某些平台上,在
HttpClient
async API上调用
Result
将导致死锁。@StephenCleary那么,如果Result可能导致死锁,我如何在没有死锁风险的情况下仍然使用HttpClient?我希望这一切都是同步的,就像WebClient的工作方式一样,同时仍然使用新的、更高级的HttpClient。@Dexter:
HttpClient
只是异步的
WebClient
支持同步和异步代码。@StephenCleary以及WebClient在同步模式下是如何工作的?“web请求基本上是一种异步操作”,因此WebClient中的同步函数可能有一些等待处理的代码。我怀疑使用WebClient的同步方法是否会产生死锁(微软可能足够聪明)。那么,我自己如何使用HttpClient来实现这一点呢?@Dexter:
WebClient
在其同步调用中阻塞。您可以调用
HttpClient
的异步方法,然后对返回的任务调用
GetAwaiter().GetResult()
。但是,在某些平台上,由于HttpClient的实现,这将导致死锁。它根本不是为那个场景设计的。