2014-03-13 129 views
4

「不能在最後條款的身體等待」,我有以下功能:尋找一種優雅的方式來解決

private async Task DoSomething(NamespaceConnectionInfo nci) 
{ 
    var session = await m_sessionProvider.GetSessionAsync(nci); 
    SomeLegacySynchronousCode(session); 
    await m_sessionProvider.EndSessionAsync(session); 
} 

其中EndSessionAsync日誌和燕子任何異常(如良好的析構函數)。

問題是SomeLegacySynchronousCode可能會拋出異常,然後會話泄漏。

很清楚,我完全爲什麼下面的代碼是非法的:

private async Task DoSomething(NamespaceConnectionInfo nci) 
{ 
    var session = await m_sessionProvider.GetSessionAsync(nci); 
    try 
    { 
     SomeLegacySynchronousCode(session); 
    } 
    finally 
    { 
     await m_sessionProvider.EndSessionAsync(session); 
    } 
} 

所以,我要尋找一個替代,這將是正確和優雅。

變我

private async Task DoSomething(NamespaceConnectionInfo nci) 
{ 
    var session = await m_sessionProvider.GetSessionAsync(nci); 
    Exception exc = null; 
    try 
    { 
     SomeLegacySynchronousCode(session); 
    } 
    catch (Exception e) 
    { 
     exc = e; 
    } 
    await m_sessionProvider.EndSessionAsync(session); 
    if (exc != null) 
    { 
     // Wrap to preserve the original stack trace. 
     throw new AggregateException(exc); 
    } 
} 

變II

private Task DoSomething(NamespaceConnectionInfo nci) 
{ 
    return m_sessionProvider.GetSessionAsync(nci).ContinueWith(t => 
    { 
     Task result = null; 
     try 
     { 
      SomeLegacySynchronousCode(t.Result); 
     } 
     finally 
     { 
      if (t.Exception == null) 
      { 
       result = m_sessionProvider.EndSessionAsync(t.Result); 
      } 
     } 
     return result; 
    }).Unwrap(); 
} 

無論是前面提到的非法異步優雅/等待版本。

我期待着改進我提出的兩個變體,因爲兩者都很難看,坦率地說。

任何想法?

回答

4

commonly-accepted answer似乎是相似的變化1:

您可以移動後的邏輯catch塊之外,並重新拋出異常 ,如果需要的話,通過使用ExceptionDispatchInfo。

static async Task f() 
{ 
    ExceptionDispatchInfo capturedException = null; 
    try 
    { 
     await TaskThatFails(); 
    } 
    catch (MyException ex) 
    { 
     capturedException = ExceptionDispatchInfo.Capture(ex); 
    } 

    if (capturedException != null) 
    { 
     await ExceptionHandler(); 

     capturedException.Throw(); 
    } 
} 

這樣,當主叫檢查異常的堆棧跟蹤 屬性,但它仍然記錄,其中內TaskThatFails它被拋出。

+0

錯過了這個問題。什麼是'ExceptionHandler'?我可以在MSDN中看到的是在'System.ServiceModel.Dispatcher'和'System.Reflection.Emit'命名空間中。沒有任何關係。 – mark

+0

'ExceptionHandler()'只是你的異常處理邏輯的佔位符。在你的情況下,它會是'm_sessionProvider.EndSessionAsync(session);' – StriplingWarrior

相關問題