2013-12-11 215 views
-1
TaskScheduler ts= TaskScheduler.FromCurrentSynchronizationContext(); 
try 
{ 
    Task<T> task1 = ... 
    task1.ContinueWith(t => 
    { 
     ... 
     Task<T> task2 = ... 
     task2.ContinueWith(u => 
     { 
      ... 
      Task<T> task3 = ... 
      task3.ContinueWith(w => 
      { 
       ... 
      }, new CancellationToken(), TaskContinuationOptions.OnlyOnRanToCompletion, ts); 
     }, new CancellationToken(), TaskContinuationOptions.OnlyOnRanToCompletion, ts); 
    }, new CancellationToken(), TaskContinuationOptions.OnlyOnRanToCompletion, ts); 
} 
catch(Exception) 
{ 
    MessageBox.Show("..."); 
}  

嗨。我有一些代碼(如上)。這對我不起作用。我有三個工作在服務器端但修改UI的任務,所以它們都應該在UI線程中生成。更重要的是:如果第二個任務失敗,第三個任務不能運行,而第二個任務只有在第一個成功完成後才能運行。所以如果第一個以失敗告終,我的任務樹應該拋出異常並中斷其餘的操作。如何以最簡單的方式實現這一目標?按任務投擲異常

UPDATE

現在我的代碼看起來像

private async void SomeMethod() 
{ 
... 
try 
{ 
     var r1 = await Method1(...); 
     var r2 = await Method2(...); 
    var r3 = await Method3(...); 
} 
catch 
{ 
     MessageBox.Show("..."); 
} 
} 

private Task<...> Method1(...) 
{ 
    Task<...> task = Task<...>.Factory.StartNew(() => 
    { 
     ... 
     try 
     { 
       // Result is null (but that's ok) so 'index out of range exception' is thrown 
       // It calls my method MyException with this exception (but I don't know in 
       // which thread and how to catch this (shouldn't be catch by async SomeMethod?) 
       result = ....Results[0]; 
     } 
     catch (Exception ex) 
     { 
       MyException(ex); 
     } 
    return result; 
    }); 
    return task; 
} 

public void MyException(Exception ex) 
{ 
    throw ex; 
} 

但我仍然不能趕上例外。

編輯 已解決。我不明白的異常(只是方法1忽略)和:

var r1 = await Method1(...); 
if(r1!=null) 
{ 
    var r2 = await Method2(...); 
    var r3 = await Method3(...); 
} 
else 
{ 
    ...do sth instead of catching ex 
} 

回答

4

最簡單的方法是用在這裏await,因爲它提供了錯誤處理,你想用很少的努力語義;讓你寫代碼,好像它是常規的同步代碼:

try 
{ 
    var firstResult = await SomethingAsync(); 
    var secondResult = await SomethingElseAsync(firstResult); 
    var finalResult = await AnotherThingAsync(secondResult); 
} 
catch 
{ 
    //handle an exception thrown by any of the above async operations. 
} 

如果你不能做到這一點(由於是在.NET 4.0),那麼你可以使用Then方法描述here也得到了語義你想:

var finalTask = SomethingAsync() 
.Then(firstResult => SomethingElseAsync(firstResult)) 
.Then(secondResult => AnotherThingAsync(secondResult)); 

finalTask.ContinueWith(t => HandleError(t.Exception), 
    TaskContinuationOptions.OnlyOnFaulted); 

Then實質上是ContinueWith通話,但使用不同的錯誤處理語義。如果任務繼續發生異常,則Then只是傳播該異常,而不是運行延續。 ContinueWith只是繼續併吞下異常。

+0

我覺得你的解決方案吸引我,但我無法處理異常。我在.NET 4.5,所以我試圖用 嘗試 { ... } 趕上(AggregateException前) { MessageBox.Show(...); } 但這並沒有從另一個線程捕獲異常。任何評論? –

+0

@ user2248836使用'Wait'不是異步的,因爲我提供的兩個解決方案都是。但是,如果這不處理錯誤,則表示該任務未被標記爲故障。要麼這個錯誤是完全不相關的,要麼這個任務本身就是創建出錯的新任務,但它不會將其標記爲故障。如果是這樣的話,解決方案就是解決這個問題,所以你不能從這個位置開始。 – Servy

+0

我其實是喜歡你說的,這個「wait」來自另一個stackoverflow的帖子。 我的解決方案在'SomethingAsync();'中出現故障,出現異常,但對我的'catch'不可見。那我該如何解決這個問題? –