调用HttpClient时,C#AsParallel被阻止
这里提到使用async/await来防止死锁。 在我的例子中,此代码仅适用于下面显示的elementsInList变量中的2或3个元素。 我想知道是否有一个数量因素会影响提出或不提出僵局 我正在尝试使用以下代码块:调用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
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)));