2014-03-03 39 views
1

我有一個看起來像這樣的控制器方法調用的任務:等待在委託

[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. 變化,使我的調用都與當它涉及到這兩種解決方案,我失去了同步上下文

。誰能幫忙?

+0

該問題似乎並不來自調用委託,儘管它來自於您正在執行阻止等待任務的事實,當你應該異步等待。 – Servy

回答

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; 
+0

適用於命令執行。但查詢變體返回一個通用任務。處理這個問題的最好方法是什麼? – jgauffin

+2

'任務'繼承'Task',所以如果你只是想「等待」它,你不需要做任何事情。如果你需要以某種方式返回結果,我會推薦'動態'。 –