【发布时间】:2014-06-20 11:16:30
【问题描述】:
问题
我在 WebAPI 中使用 DelegatingHandler 来读取响应内容并将其审核到数据库中。
当代码到达 .ReadAsStringAsync() 时,它似乎会锁定并阻止其他请求完成。我只知道这一点,因为当我删除违规行时,它可以完美运行。
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 和 Controller/ModelBinder)读取内容时,可能会发生这种情况......或者更具体地说,当一个人试图读取 .Result 的异步响应,但另一个实例已经读取了结果/响应流,则为空。
我的第一个请求命中一个简单的控制器,但第二个请求命中一个具有属性的控制器,该属性检查 Action 参数“id”以检查其不为空。我已经读过,当 DelegatingHandler 和控制器 ModelBinder 都试图从响应中读取时,你会遇到死锁。
替代方法(同样失败)
我也尝试过使用 .ReadAsByteArrayAsync() 的其他方法(如在其他 SO 问题中所见),但这似乎仍然锁定。我知道这种方法不使用 .Result 方法,而是直接从响应流中读取(不知何故)。
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);
请帮忙!
【问题讨论】:
-
如果您在代码中的其他任何位置(在外部调用堆栈上)有
task.Wait()或task.Result,通常会发生这种情况。是这样吗? -
@peter.swallow:你能创建一个可靠地重现问题的小例子吗?
标签: c# async-await httphandler dotnet-httpclient