使用HttpClient
发送http请求时,我遇到间歇性死锁,有时他们永远不会在我的代码中返回await SendAsync
。我能够找出在HttpClient
/ HttpClientHandler
内部处理请求的线程由于某种原因在死锁期间有SynchronizationContext
。我想弄清楚如何使用线程最终得到SynchronizationContext
,而通常他们没有。{我会假设导致设置此SynchronizationContext
的任何对象在Thread
上也会阻塞,这会导致死锁。
我能否在TPL ETW事件中看到任何相关内容?
我该如何解决这个问题?
编辑2:
我注意到这些死锁的地方是在windows服务中的wcf ServiceContract
(参见下面的代码)中。导致问题的SynchronizationContext
实际上是WindowsFormsSynchronizationContext
,我认为这是由某些控件创建并且未正确清理(或类似的东西)引起的。我意识到几乎肯定不应该是Windows服务中的任何窗体形式的东西,我并不是说我同意它是如何被使用的。但是,我没有使用它编写任何代码,而且我不能轻易地改变所有的引用。
编辑:这是我遇到问题的wcf服务的一般概念示例。它是一个简化版本,而不是确切的代码:
[ServiceContract]
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Multiple)]
internal class SampleWcfService
{
private readonly HttpMessageInvoker _invoker;
public SampleWcfService(HttpMessageInvoker invoker)
{
_invoker = invoker;
}
[WebGet(UriTemplate = "*")]
[OperationContract(AsyncPattern = true)]
public async Task<Message> GetAsync()
{
var context = WebOperationContext.Current;
using (var request = CreateNewRequestFromContext(context))
{
var response = await _invoker.SendAsync(request, CancellationToken.None).ConfigureAwait(false);
var stream = response.Content != null ? await response.Content.ReadAsStreamAsync().ConfigureAwait(false) : null;
return StreamMessageHelper.CreateMessage(MessageVersion.None, "GETRESPONSE", stream ?? new MemoryStream());
}
}
}
将ConfigureAwait(false)
添加到上面的2个地方并没有完全解决我的问题,因为用于服务进入此处的wcf请求的线程池线程可能已经有SynchronizationContext
。 在这种情况下,请求会一直通过整个GetAsync
方法并返回。但是,它仍然在System.ServiceModel.Dispatcher.TaskMethodInvoker
中陷入僵局,因为在那个微软代码中,它并没有使用ConfigureAwait(false)
,我想假设有充分的理由(for reference ):
var returnValueTask = returnValue as Task;
if (returnValueTask != null)
{
// Only return once the task has completed
await returnValueTask;
}
感觉真的错了,但是将它转换为使用APM(开始/结束)而不是使用任务修复此问题?或者,是唯一能够正确修正未正确清除其SynchronizationContext
的代码的修复程序吗?
答案 0 :(得分:2)
尝试以下;我在类似的情况下成功进入异步兔洞。
var responsebytes = await response.Content.ReadAsByteArrayAsync();
MemoryStream stream = new MemoryStream(filebytes);
响应流变量。
希望它有所帮助。