2

我正在閱讀一本名爲C#的Pro .NET 4並行編程的書,由Adam Freeman編寫。在第2章第13頁中,它討論了使用Task<int>通過使用task1.Result來返回結果以等待它結束。我不明白爲什麼task2必須等待task1才能完成。他們在不同的線程。C#.net 4並行編程

這件事情,象下面這樣:

Task<int> task1 = new Task<int>(() => { ... ; return sum }); 
task1.Start(); 
Console.WriteLine("Result 1: {0}", task1.Result); 

Task<int> task2 = new Task<int>(() => { ... ; return sum }); 
task2.Start(); 
Console.WriteLine("Result 2: {0}", task2.Result); 

如果我移動到下面的行好像task1底部依然執行先不管多少次,我試過。

Console.WriteLine("Result 1: {0}", task1.Result); 

這是怎麼發生的?

回答

0

首先實際完成的任務 - 即首先命中它的返回語句 - 在形式上是不可預測的。他們可以在接受他們的結果之前完成他們的工作。

如果您的示例任務所做的工作不是很大,那麼即使您先不接受其結果(或者以Java線程術語加入它),task1仍將首先完成。那是因爲你先開始吧。

想必你知道task1先完成。是否有一個Console.WriteLine埋在你的任務代碼中?如果是這樣,請記住,控制檯子系統會對操作進行序列化,因此在第二個任務啓動之前,第一個要使用它的任務將完成。你可以這樣想:你的兩項任務競賽到控制檯,而勝利者則需要全部。

task1在這場比賽中具有不公平的優勢,因爲它在您的主線程開始構建task2之前已關閉並運行,您的第二個new

+0

感謝您的回答 – Fei 2012-01-02 15:03:22

3

Task.Result塊直到Task完成。

它必須爲了有結果返回!

因此,在您的第一個示例中,task2甚至在task1已完成時纔會啓動。

如果您將task1.Result移動到底部,則不確定哪個任務首先完成,但是您的語句將按順序執行。

+0

尼古拉斯,謝謝你的回覆。我可以理解任務。結果將等到任務結束。如果task1已經啓動,我不能啓動另一個任務(線程)執行?還有另外一個例子,如下所示:foreach(消息中的字符串消息){Task tsk = new Task(obj => printMsg(obj),msg); tsk.Start();}。 foreach循環內的這些任務並行執行。 – Fei 2012-01-02 14:47:15

0

嘗試使用task.Wait()方法。

 Task<int> task1 = new Task<int>(() => { int sum = 0; return sum; }); 
     task1.Start(); 
     task1.Wait(); 
     Console.WriteLine("Result 1: {0}", task1.Result); 

     Task<int> task2 = new Task<int>(() => { int sum = Enumerable.Range(1, 10).Sum(); return sum; }); 
     task2.Start(); 
     task1.Wait(); 
     Console.WriteLine("Result 2: {0}", task2.Result); 
+0

它應該給出相同的結果,但由於您明確地「等待」,因此讀起來更容易。 – Bengie 2012-01-02 14:59:31

+0

感謝您的回答。 – Fei 2012-01-02 15:06:07

0

「Console.WriteLine(」Result 1:{0}「,task1.Result);」無法運行,直到task1完成,所以它等待/阻止。

雖然任務確實彼此獨立運行,但調用線程按順序調用console.writeline。這兩項任務的結果被迫按順序排列。

0

Task task1 = new Task(() => { ... ; return sum });
task1.Start();
Task task2 = new Task(() => { ... ; return sum });
task2.Start();
task1.Wait()
Console.WriteLine("Result 1: {0}", task1.Result);
task2.Wait()
Console.WriteLine("Result 2: {0}", task2.Result);

試試這個。在這裏你需要在調用console.writeline之前啓動這兩項任務。