2014-03-01 63 views
4

期待這是我的代碼子任務不被父任務

static void Main(string[] args) 
{ 
    List<Thing> collection = new List<Thing> 
    { 
     new Thing { IntProp = 1, BoolProp = true }, 
     new Thing { IntProp = 1, BoolProp = true }, 
     new Thing { IntProp = 2, BoolProp = true }, 
     new Thing { IntProp = 1, BoolProp = false } 
    }; 

    int number = 0; 

    var task = Task.Factory.StartNew<bool>(() => 
    { 
     TaskFactory ts = new TaskFactory(TaskCreationOptions.AttachedToParent, TaskContinuationOptions.ExecuteSynchronously); 

     foreach (var item in collection) 
     { 
      if (item.BoolProp) 
      { 
       ts.StartNew(() => 
        number += GetNum1(item.IntProp)); 
      } 
      else 
      { 
       ts.StartNew(() => 
        number += GetNum2(item.IntProp)); 
      } 
     } 

     return true; 
    }); 

    task.Wait(); 

    Console.WriteLine(number); 
} 

這裏是GetNum1定義和GetNum2

static int GetNum1(int num) 
{ 
    for (int i = 0; i < 1000000000; i++) { } // simulate some job 

    return 10; 
} 

static int GetNum2(int num) 
{ 
    for (int i = 0; i < 500000000; i++) { } // simulate some job 

    return 3; 
} 

這裏是Thing

class Thing 
{ 
    public bool BoolProp { get; set; } 
    public int IntProp { get; set; } 
} 

基本上我正在做的只是創建收集Thing對象。然後我創建一個單獨的父任務,這將有幾個子任務(它應該等待,我猜)。

有一個number變量,它由子任務增加GetNum1GetNum2方法(10或3)返回的數量。我猜測上面的代碼應該輸出33(10 + 10 + 10 + 3),而10輸出,因爲只是第一個子任務等待。如果我在代碼中放置斷點並逐步執行,那麼輸出是正確的。爲什麼發生這種情況。它是否必須在父任​​務中的foreach循環中做些什麼?請不要開始提問像「爲什麼你需要這個」和「沒有必要這樣」的問題,這只是一個示例代碼。

回答

5

父任務實際上正在等待(而不是「等待」)子任務。你的問題是,代碼訪問從多個線程number變量不同步:

var mutex = new object(); 
int number = 0; 

var task = Task.Factory.StartNew<bool>(() => 
{ 
    TaskFactory ts = new TaskFactory(TaskCreationOptions.AttachedToParent, TaskContinuationOptions.ExecuteSynchronously); 

    foreach (var item in collection) 
    { 
     if (item.BoolProp) 
     { 
      ts.StartNew(() => 
      { 
       var value = GetNum1(item.IntProp); 
       lock (mutex) number += value; 
      }); 
     } 
     else 
     { 
      ts.StartNew(() => 
      { 
       var value = GetNum2(item.IntProp); 
       lock (mutex) number += value; 
      }); 
     } 
    } 

    return true; 
}); 

task.Wait(); 

lock (mutex) 
    Console.WriteLine(number); 

推薦閱讀:Parallel TasksDynamic Task Parallelism

+0

在Console.WriteLine()仍然可以有結果之前,我還沒有** lock(mutex)** 33還有 –

+2

@ V-SHY:在讀取時跳過'lock'有時可以工作,但線程本地緩存可以搞砸你先進的硬件。 –