2013-02-06 272 views
1

在C#中,是否可以立即退出正在進行的Parallel.For循環。在調用loopState.Stop()之後,以下代碼可能需要一整秒的時間才能退出循環。立即退出c中的Parallel.For循環#

static void Main(string[] args) 
{ 
    Stopwatch watch = new Stopwatch(); 

    Parallel.For(0, 50, (i, loopState) => 
    { 
     Console.WriteLine("Thread:" + Thread.CurrentThread.ManagedThreadId + "\tIteration:" + i); 
     Thread.Sleep(1000); 

     if (i == 0) 
     { 
      watch.Start(); 
      loopState.Stop(); 
      return; 
     } 
    }); 

    Console.WriteLine("Time Elapsed since loopState.Stop(): {0}s", watch.Elapsed.TotalSeconds); 
    Console.ReadKey(); 
} 

輸出

Thread:10  Iteration:0 
Thread:6  Iteration:12 
Thread:11  Iteration:24 
Thread:12  Iteration:36 
Thread:13  Iteration:48 
Thread:13  Iteration:49 
Thread:12  Iteration:37 
Time Elapsed since loopState.Stop(): 0.9999363s 

有什麼辦法更快地做到這一點? 謝謝!

回答

3

是的,這是可能的。看看this關於並行編程問題的文章。這是給你的摘錄出來的:

如果我不希望浪費資源,要立即停止所有 計算後,我點擊取消?在這種情況下,我必須定期檢查 在執行長時間運行的方法內的某處取消令牌的狀態 。由於我 宣佈取消標記爲一個字段,我可以簡單地使用它在 該方法。採用傳統的StopBreak不會導致任務

public double SumRootN(int root) 
{ 
    double result = 0; 
    for (int i = 1; i < 10000000; i++) 
    { 
     tokenSource.Token.ThrowIfCancellationRequested(); 
     result += Math.Exp(Math.Log(i)/root); 
    } 
    return result; 
} 

您所遇到被立即取消。據this文章MSDN上,

在此背景下,「破發」是指在之前的當前線程的當前迭代是所有線程 完成所有迭代,並 然後退出循環。 「停止」意味着只要 方便,就停止所有迭代。

所以你不能強迫它立即停止使用傳統的方法。您將需要使用像我在開始時提到的方法。

希望這可以幫助你!

+0

不幸的是,我的表現沉重的呼叫是在第三方庫內,但我可以用這種技術提高我的表現。謝謝! – rob

+0

不理會最後的評論。這實際上在性能上有很大的不同。雖然我用loopState.ShouldExitCurrentIteration而不是tokenSource。 – rob

+0

@rob很高興爲你效勞。感謝您的反饋意見。 – FrostyFire

1

問題是循環體的運行時間。 loopState.Stop()從頭開始停止任何新的循環迭代,並等待當前正在運行的任何完成循環。