2010-09-16 18 views
5

我的代碼運行的4個功能中的信息填寫(用調用)的一類,例如:Parallel.Invoke - 異常處理

class Person 
{ 
    int Age; 
    string name; 
    long ID; 
    bool isVegeterian 

    public static Person GetPerson(int LocalID) 
    { 
     Person person; 
     Parallel.Invoke(() => {GetAgeFromWebServiceX(person)}, 
         () => {GetNameFromWebServiceY(person)}, 
         () => {GetIDFromWebServiceZ(person)}, 
         () => 
         { 
          // connect to my database and get information if vegeterian (using LocalID) 
          .... 
          if (!person.isVegetrian) 
           return null 
          .... 
         }); 
    } 
} 

我的問題是:我不能,如果他不是一個vegeterian返回null,但我希望能夠停止所有線程,停止處理並返回null。如何實現?

回答

4

那麼,你可以從你的行動中拋出異常,在GetPerson(即在Parallel.Invoke周圍放置一個try/catch塊)捕獲AggregateException,檢查它是否是正確的異常,並返回null。

完成所有的事情除了停止所有的線程。我認爲除非您開始使用取消令牌,否則您很難輕鬆停止已運行的任務。您可以通過保留boolean值來指示目前爲止的任何任務是否失敗,並使每項任務在啓動之前檢查它,從而可以停止執行進一步的任務...這有點難看,但會起作用。

我懷疑使用「完整」任務而不是Parallel.Invoke會使所有這些都更加優雅。

7

要儘早退出Parallel.Invoke你必須做三兩件事:

  1. 計劃檢測是否要早在前動作退出動作。然後它會更早安排(也許是第一次,但不能保證),所以你會很快知道你是否想退出。
  2. 當您檢測到錯誤並按照Jon的答案指出AggregateException時,拋出異常。
  3. 使用取消標記。但是,如果您有機會檢查其IsCancellationRequested屬性,這纔有意義。

你的代碼,然後將如下所示:

var cts = new CancellationTokenSource(); 
try 
{ 
    Parallel.Invoke(
     new ParallelOptions { CancellationToken = cts.Token }, 
     () => 
     { 
      if (!person.IsVegetarian) 
      { 
       cts.Cancel(); 
       throw new PersonIsNotVegetarianException(); 
      } 
     }, 
     () => { GetAgeFromWebServiceX(person, cts.Token) }, 
     () => { GetNameFromWebServiceY(person, cts.Token) }, 
     () => { GetIDFromWebServiceZ(person, cts.Token) } 
    ); 
} 
catch (AggregateException e) 
{ 
    var cause = e.InnerExceptions[0]; 
    // Check if cause is a PersonIsNotVegetarianException. 
} 

然而,正如我所說的,取消標記纔有意義,如果你可以檢查它們。因此,GetAgeFromWebServiceX應該有一個機會來檢查取消令牌並提前退出,否則將令牌傳遞給這些方法是沒有意義的。

1

無論如何,您首先需要從數據庫加載您的Person?因爲它是你的代碼用空來調用Web服務。

如果你的邏輯確實是順序的,那麼順序執行,只有並行執行纔有意義。