2012-05-19 166 views
0

我在控制檯應用程序(不確定這是否與它有關)和使用任務時遇到了一個奇怪的問題。Threading.Tasks:WaitAll的概念()

大多數例子顯示故意調用一個例外測試/解釋爲WaitAll的概念 - 但對我來說,這似乎我在做某種根本性錯誤(或不完全明白)。

Task<int> task1 = Task<int>.Factory.StartNew(()=> foo(arg)); 
Task<int> task2 = Task<int>.Factory.StartNew(()=> bar(arg)); 

Task<int>[] tasks = {task1, task2}; 

try 
{ 
    Task.WaitAll(tasks); //hits this far 

    if((int)task1.Result * (int)task2.Result == 99) //this seems to never get hit 
    { 
     System.Environment.Exit(0); //so this isn't called    
    } 
    else 
    { 
     System.Environment.Exit(1); // neither is this called 
    } 
} 
catch 
{ 
    ..... 

在它上面似乎if塊是打不到那麼返回既不退出代碼 - 因此控制檯應用程序掛起。

也不會拋出異常 - 我可以證實這一點,因爲全部任務實際上已完成 - 我只是沒有包括上面的catch部分以簡潔起見。

這些任務很快完成 - 它們沒有掛起,所以它不像Task.WaitAll仍然在等待 - 或者它可能是這樣,這就是我錯過的東西(它在等什麼)?

任何想法,建議或殘酷的更正?謝謝!

+2

我們需要更多地瞭解這些任務。您對WaitAll的理解是正確的,它會在任務完成時返回,或者在任何任務中拋出異常時拋出異常。 (請注意,只有在完成所有任務後纔會拋出異常) – caesay

+0

片段確實需要證明foo或bar引發異常。否則你應該沒有問題用調試器診斷,它會清楚地顯示你的catch塊受到打擊。 –

+1

作爲一個方面說明,你不需要'(int)'強制轉換,Result中的類型已經是'(int)'了。 – svick

回答

4

只是爲了論證的緣故,我做了一個小測試(如下所示) - 它表明你的任務之一是掛起,而不是返回一個值。

 Task<int> task1 = Task<int>.Factory.StartNew(() => 
     { 
      Thread.Sleep(2000); 
      return 10; 
     }); 
     Task<int> task2 = Task<int>.Factory.StartNew(() => 15); 
     Task<int>[] tasks = {task1, task2}; 
     try 
     { 
      Stopwatch sw = new Stopwatch(); 
      sw.Start(); 
      Task.WaitAll(tasks); 
      sw.Stop(); 
      Console.WriteLine(String.Format("tasks completed in {0}ms", sw.ElapsedMilliseconds)); 
     } 
     catch 
     { 
      Console.WriteLine("Error"); 
     } 
     Console.ReadLine(); 

如果您運行的是,它會打印tasks completed in 2000ms(給予或採取幾毫秒)。我所做的只是複製/粘貼你的代碼並添加我自己的任務。

因此,如果您認爲"The tasks are [...] not hanging..."是假的 - 它們必須懸掛。

+0

謝謝我會更多地開展一項我可能假設完成的任務。它涉及[SSH.Net](http://sshnet.codeplex。com /) - 它做它需要做的事情(寫一個文件到SFTP位置),但也許這個任務沒有正確返回一個int值。 – EdSF

+0

謝謝 - 這實際上是問題。似乎有一些[SSH.NET Disconnect()間歇性問題](http://sshnet.codeplex.com/workitem/792)。雖然問題被標記爲關閉,但看起來不應該是這樣。 [另一個問題](http://sshnet.codeplex.com/workitem/1140)指向聲音相關的Disconnect()。無論如何,感謝您的幫助! – EdSF

1

正如上文所述,任務必須懸掛。爲了檢查這個,我建議給你的WaitAll呼叫一個默認的時間。你可以通過在代表毫秒呼叫必須等待的任務將超過在數一個int做到這一點。試試這個

Task.WaitAll(tasks, 10000); //Set to wait for 10 seconds 

然後看看是否有異常,還是你的「如果」聲明被擊中。如果這樣做有效,那麼可以嘗試更大的時間間隔來查看任務正在進行的情況。

此外,我會建議運行在沒有任務(即順序)作爲測試工具的foo和bar內的代碼,以瞭解這兩個示例方法是否存在任何特定問題。

+0

感謝您的建議。這*可能*因爲我等待返回值而失敗 - 重新:因此,即使它們實際執行任務*,它總是會「失敗」*。我知道這聽起來很奇怪 - 但在我的情況下,任務完成無一例外。無論是(或兩者)他們只是因爲某種原因沒有返回值(我已經在第三方開源庫中有一個嫌疑犯)。 – EdSF

+0

所以,當你說「任務完成無例外」時,if塊必須被擊中,因爲它是執行模型中的下一個邏輯語句。你是否暗示「if」語句從不執行,或者它執行了但是這些任務沒有返回值? – Nikhil

+0

感謝您的諮詢!問題確定並解決。 'if'不會間歇運行(lib問題 - 參見上文)。任務真的**部分完成**(因爲它不會返回值 - 我只看着任務的一部分)。 – EdSF