僵局的WebAPI从异步DelegatingHandler异步读取响应内容 [英] Deadlock reading async response content from async DelegatingHandler in webapi
问题描述
问题
我使用的WebAPI一个DelegatingHandler读取响应的内容,并将其审计数据库。
I'm using a DelegatingHandler in WebAPI to read the response Content and audit it to the database.
当code到达.ReadAsStringAsync()它似乎锁定和完成prevent其他请求。我只知道这一点,因为当我删除有问题的线,它完美的作品。
When the code gets to .ReadAsStringAsync() it appears to lock and prevent other requests from completing. I only know this, because when I remove the offending line, it works perfectly.
public static void Register(HttpConfiguration config)
{
config.MessageHandlers.Add(new ResourceAuditHandler());
}
public class ResourceAuditHandler : DelegatingHandler
{
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request,
CancellationToken cancellationToken)
{
var response = await base.SendAsync(request, cancellationToken);
string content = "";
if (response.Content != null)
{
//THIS SEEMS TO CREATE DEADLOCK!
content = await response.Content.ReadAsStringAsync();
}
AuditResponseToDatabase(content);
return response;
}
}
可能的原因
我读过这可能发生在应用程序的两位试图读取相同的请求/响应的内容(DelegatingHandler和控制器/ ModelBinder的)...或者,当一个人试图读取更具体的在 。结果异步响应,但另一个实例已经阅读了结果/响应流中,然后空。
I've read this can happen when two bits of the application are trying to read the content from same request/response (a DelegatingHandler and Controller/ModelBinder)... Or more specifically when one tries to read the .Result of the async response, but the other instance has already read the Result / Response Stream, which is then null.
我的第一个要求,打一个简单的控制器,但第二个请求,击中一个控制器,检查行动参数ID,以检查它不是空的属性。我读过,当两个一DelegatingHandler和ModelBinder的正试图从你得到僵局响应阅读器。
My first request, hits a simple controller, but the second request, hits a controller with an attribute that checks the Action parameter "id" to check its not null. I've read that, when both a DelegatingHandler and the controller ModelBinder are trying to read from the Response you get deadlock.
替代方法(这也失败了)
我也尝试使用它使用的 .ReadAsByteArrayAsync()其他的方法(如在其他做题所示),但这似乎仍然锁定。我明白,这种方法不使用。结果的办法,直接从响应流(不知)。
I've also tried using the other approach (as seen in other SO questions) which uses .ReadAsByteArrayAsync() but this still seems to lock. I understood that this method doesn't use the .Result approach and reads it directly from the response stream (somehow).
var response = await base.SendAsync(request, cancellationToken);
string content= "";
if (response.Content != null)
{
var bytes = await response.Content.ReadAsByteArrayAsync();
responseContent = Encoding.UTF8.GetString(bytes);
}
AuditResponseToDatabase(content);
请帮帮忙!
推荐答案
彼得,首先,你对这个僵局的原因。尝试使用异步/的await
一路下跌。换句话说,不要在阻止异步
code。你应该做的另一件事是使用 .ConfigureAwait(假)
:
Peter, first of all, you are right about the cause of this deadlock. Try to use async/await
all the way down. In other words, do not block on async
code. Another thing you should do is using the .ConfigureAwait(false)
:
var response = await base.SendAsync(request, cancellationToken).ConfigureAwait(false);
string content = "";
if (response.Content != null)
{
content = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
}
更多信息,你可以找到在这个链接
如果没有上述工作,请提供一个完整的例子,好吗?
If none of the above work, please provide a complete example, ok?
希望这有助于!
这篇关于僵局的WebAPI从异步DelegatingHandler异步读取响应内容的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!