僵局的WebAPI从异步DelegatingHandler异步读取响应内容 [英] Deadlock reading async response content from async DelegatingHandler in webapi

查看:2153
本文介绍了僵局的WebAPI从异步DelegatingHandler异步读取响应内容的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

问题

我使用的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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆