调用HttpClient时,C#AsParallel被阻止

调用HttpClient时,C#AsParallel被阻止,c#,multithreading,thread-safety,dotnet-httpclient,C#,Multithreading,Thread Safety,Dotnet Httpclient,这里提到使用async/await来防止死锁。 在我的例子中,此代码仅适用于下面显示的elementsInList变量中的2或3个元素。 我想知道是否有一个数量因素会影响提出或不提出僵局 我正在尝试使用以下代码块: var responses = elementsInList.AsParallel() .WithDegreeOfParallelism(elementsInList.Count) .Select(ele

这里提到使用async/await来防止死锁。 在我的例子中,此代码仅适用于下面显示的elementsInList变量中的2或3个元素。 我想知道是否有一个数量因素会影响提出或不提出僵局

我正在尝试使用以下代码块:

var responses = elementsInList.AsParallel()
                    .WithDegreeOfParallelism(elementsInList.Count)
                    .Select(elementInList => GetResponse(elementInList, timeout)).ToList();
(……)

公共JObject GetResponse(JObject请求,TimeSpan超时) { var endpoint=ConfigurationManager.AppSettings.Get(“MyEndPoint”); 尝试 { 使用(var client=new HttpClient()) { client.DefaultRequestHeaders.Accept.Clear(); client.Timeout=超时; IList formatters=GetMediaTypeFormatters(); HttpResponseMessage response=client.postsjsonasync(端点,请求).Result; if(响应。IsSuccessStatusCode) { 返回response.Content.ReadAsAsync(格式化程序).Result; } 抛出新异常(response.ReasonPhrase); } } 捕获(例外情况除外) { 返回新的JObject() { 新JProperty(“异常”、“无效响应”。+ex.Message) }; } } 如果我调试代码,当.AsParallel行被命中时,代码会被阻塞,它永远不会返回答案或转到下一行。 那里似乎正在发生僵局


我想添加的一个细节是,如果我将此代码与2或3个元素一起使用,它可以正常工作,但是,当调用类似于30-50个元素时,它会失败。在第二种情况下,是否存在可能引发死锁的数量因素,而不是在第一种情况下?我很好奇它是否会影响,或者它是否也可以仅由2或3个元素生成

一般的经验法则是,只有当你的应用程序需要进行CPU密集型工作时,才使用并行技术。对于I/O绑定的工作,使用异步技术。对于<>强>非常罕见的需要并行和异步代码的情况,考虑TPL数据流等技术。

在您的情况下,没有CPU密集型工作要做,因此请删除所有并行内容,只需使用
async
/
wait

public async Task<JObject> GetResponseAsync(JObject request, TimeSpan timeout)
{
  var endpoint = ConfigurationManager.AppSettings.Get("MyEndPoint");
  try
  {
    using (var client = new HttpClient())
    {
      client.DefaultRequestHeaders.Accept.Clear();
      client.Timeout = timeout;

      IList<MediaTypeFormatter> formatters = GetMediaTypeFormatters();
      HttpResponseMessage response = await client.PostAsJsonAsync(EndPoint, request);

      if (response.IsSuccessStatusCode)
        return await response.Content.ReadAsAsync<T>(formatters);

      throw new Exception(response.ReasonPhrase);
    }
  }
  catch (Exception ex)
  {
    return new JObject()
    {
      new JProperty("Exception", "Invalid response. " + ex.Message)
    };
  }
}

.Result
本质上是
。等待
-确保阅读链接的副本,如有必要,更新问题/评论以重新打开。您是对的,感谢链接到其他类似案例。在我的情况下,代码显示了一些元素的工作原理。是否存在可能引发/产生死锁的数量因素?或者即使有两个元素,死锁也必须引发?不确定为什么此代码只适用于很少的元素。在ASP.Net/WinForms同步上下文中运行的线程调用Wait/Result时,它应该立即死锁。我不确定
.AsParallel
如何并行运行单独的操作,但我假设一些操作会在当前UI线程上运行,并导致死锁。检查挂起时的调用堆栈可以揭示问题的确切来源。非常感谢您的回答。这是否意味着当我们将HttpClient ReadAsAsync与多个线程/任务一起使用时,我们需要强制使用async/Wait?或者在某些情况下不会发生死锁?@AlbertoMontellano:如果您使用的是
HttpClient
,那么您应该使用
wait
。线程/任务的数量与此无关。是的,有些情况下不会出现死锁,但你不应该依赖它们。谢谢你的指导和澄清。
public async Task<JObject> GetResponseAsync(JObject request, TimeSpan timeout)
{
  var endpoint = ConfigurationManager.AppSettings.Get("MyEndPoint");
  try
  {
    using (var client = new HttpClient())
    {
      client.DefaultRequestHeaders.Accept.Clear();
      client.Timeout = timeout;

      IList<MediaTypeFormatter> formatters = GetMediaTypeFormatters();
      HttpResponseMessage response = await client.PostAsJsonAsync(EndPoint, request);

      if (response.IsSuccessStatusCode)
        return await response.Content.ReadAsAsync<T>(formatters);

      throw new Exception(response.ReasonPhrase);
    }
  }
  catch (Exception ex)
  {
    return new JObject()
    {
      new JProperty("Exception", "Invalid response. " + ex.Message)
    };
  }
}
var responses = await Task.WhenAll(
    elementsInList.Select(x => GetResponseAsync(x, timeout)));