在WebApi阻塞中使用AwaitAsync进行并行调用

时间:2015-07-27 07:52:22

标签: c# async-await

我是一个webApi操作,它在||中执行2个操作在内部调用HttpClient sendAsync。如果我应用调试器并执行调用,它将工作并返回。如果我删除调试器,两个异步调用仍然有效(在Fiddler中检查)但WebApi操作的调用者没有得到任何响应(使用AdvanceRest chrome插件)。从其他线程,我可能没有正确使用async / await并且与ASP.NET synchronizationContext相关

//**WEB API Controller***
class SomeController 
{
     public HttpResponseMessage Get()
     {
         Client someClient = new Client();
         aResponse = new aResponse();
         bResponse = new bResponse();
         Parallel.Invoke(
         () => {aResponse = someClient.a()},
         () => {bResponse = someClient.b()});

        var response = {a=aResponse, b=bResponse};
        return Response.Create(OK, response}
     }

class SomeClient
{
    AResponse a()
    {
        var clientResponse = ClientMgr.Execute("url");  
        return new AResponse {HttpClientResponse = clientResponse.Result}
    }

    BResponse b()
    {
        var clientResponse = ClientMgr.Execute("url");  
        return new BResponse {HttpClientResponse = clientResponse.Result}
    }
}

//Utility CLASS
public class ClientMgr
{
    public static async Task<HttpResponseMessage> Execute(string url)
    {
        request = new HttpRequestMessage();
        //....request fill
        HttpClient client = new HttpClient();
        var response = await client.SendAsync(request);
        client.dispose();
        return response;
    }
}

public class AResponse 
{
    HttpResponseMessage HttpClientResponse {get;set;}
    // Some other properties....
}

为什么操作会在我使用断点时返回响应,但是当我删除它们时,它不会返回响应?

1 个答案:

答案 0 :(得分:3)

您的问题(除了您发布的代码无法编译的事实)是您在调试时,异步操作实际上已完成。当您不进行调试时,他们不会,并且会返回Task<YourResponse>,而不是Task的实际结果。

为了使其正常工作,请将您的方法标记为async并使用Task.WhenAll异步等待这两项任务:

[HttpGet]
public async Task<HttpResponseMessage> GetAsync()
{
    Client someClient = new Client();
    var aTask = someClient.AAsync();
    var bTask = someClient.BAsync();

    await Task.WhenAll(aTask, bTask);
    var response = { a = aTask.Result, b = bTask.Result };
    return Response.Create(OK, response}
}

附注 - 当您进行IO绑定操作时,您不需要使用Paralle.Invoke。这些是冗余线程,将被阻止等待IO的完成。