等待代理中调用的任务

时间:2014-03-03 20:15:01

标签: c# async-await asp.net-web-api2

我有一个控制器方法,如下所示:

[HttpPut, Route("cqs/command")]
public HttpResponseMessage Command([ValueProvider(typeof(HeaderValueProviderFactory))] string typeName)
{
    object reply = null;
    var code = HttpStatusCode.OK;
    try
    {
        var cmdObject = DeserializeRequest(typeName);
        var method = _commandMethod.MakeGenericMethod(type);
        method.Invoke(this, new object[] { request });
    }
    catch (Exception exception)
    {
        code = HttpStatusCode.InternalServerError;
        reply = exception;
    }

    var responseMsg = new HttpResponseMessage(code);
    if (reply != null)
    {
        responseMsg.Headers.Add("X-TypeName", reply.GetType().AssemblyQualifiedName);
        var replyJson = JsonConvert.SerializeObject(reply);
        responseMsg.Content = new StringContent(replyJson, Encoding.UTF8, "application/json");
    }
    return responseMsg;
}

调用以下方法:

private void ExecuteCommand<T>(T command) where T : Command
{
    var task = _commandBus.ExecuteAsync(command);
    task.Wait(TimeSpan.FromSeconds(10));
}

原因是_commandBus只有一个我需要调用的泛型方法。

然而问题是ExecuteCommand似乎在某些时候陷入僵局。我无法弄清楚为什么。 ICommandBus.ExecuteAsync方法将使用async / await调用其他任务,因此它可能是某种死锁,因为WebApi使用同步上下文? (await vs Task.Wait - Deadlock?

因此,如果我理解正确,可能有两种解决方案:

  1. 一直使用async / await。但是,如何在使用MethodInfo
  2. 调用方法时这样做
  3. 更改,以便我的调用与同步上下文一起使用
  4. 两种解决方案都让我迷失了方向。有人可以帮忙吗?

1 个答案:

答案 0 :(得分:4)

更改ExecuteCommand<T>,使其看起来像这样(我假设你的实际代码会在超时时某事):

private async Task ExecuteCommandAsync<T>(T command) where T : Command
{
  var timeout = Task.Delay(TimeSpan.FromSeconds(10));
  var task = _commandBus.ExecuteAsync(command);
  await Task.WhenAny(task, timeout);
}

并进行任何调用async Task。然后,当您调用该方法时,您可以执行以下操作:

var task = method.Invoke(this, new object[] { request }) as Task;
await task;