【问题标题】:Wait on a task invoked in a delegate等待委托中调用的任务
【发布时间】:2014-03-03 20:15:01
【问题描述】:

我有一个看起来像这样的控制器方法:

[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. 一直使用异步/等待。但是在使用MethodInfo 调用方法时我该怎么做呢?
  2. 更改以便我的调用与同步上下文一起工作

当谈到这两种解决方案时,我都迷失了。有人可以帮忙吗?

【问题讨论】:

  • 问题似乎不是来自于调用委托,而是来自于你正在对任务进行阻塞等待,而此时你应该异步等待。

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


【解决方案1】:

更改ExecuteCommand&lt;T&gt; 使其看起来像这样(我假设您的实际代码会在超时时某些事情):

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;

【讨论】:

  • 这适用于命令执行。但是 Query 变体返回一个通用任务。处理这个问题的最佳方法是什么?
  • Task&lt;T&gt; 继承自 Task,所以如果你只想 await 它你不需要做任何其他事情。如果您需要以某种方式返回结果,我建议您使用dynamic
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多