什麼是暫停和停止(在結束之前)parallel.foreach最有效的方法?Parallel.Foreach c#暫停和停止功能?
Parallel.ForEach(list, (item) =>
{
doStuff(item);
});
什麼是暫停和停止(在結束之前)parallel.foreach最有效的方法?Parallel.Foreach c#暫停和停止功能?
Parallel.ForEach(list, (item) =>
{
doStuff(item);
});
Damien_The_Unbeliver有一個很好的方法,但那是隻有當你想有一些外部過程停止循環。如果你想讓循環突破,就像在普通的for
或foreach
循環中使用break
一樣,你將需要使用a overload,它具有ParallelLoopState
作爲循環體的一個參數。 ParallelLoopState
有兩個功能與您想要執行的操作相關,即Stop()
和Break()
。
Stop()
將停止處理單元在系統的儘早這意味着更多的迭代可以調用停止(後)進行,並不能保證你停在元素之前來到的元素甚至已經開始的功能處理。
功能Break()
執行完全一樣,但是Stop()
它也將評估您在叫Break()
該項目之前來到IEnumerable
的所有元素。當你不關心處理元素的順序時,這是非常有用的,但是你必須處理所有的元素直到你停止的點。
檢查從foreach返回的ParallelLoopResult以查看該foreach是否提前停止,並且如果使用了Break()
,那麼它處理的最低編號項目是什麼。
Parallel.ForEach(list, (item, loopState) =>
{
bool endEarly = doStuff(item);
if(endEarly)
{
loopState.Break();
}
}
);
//Equivalent to the following non parallel version, except that if doStuff ends early
// it may or may not processed some items in the list after the break.
foreach(var item in list)
{
bool endEarly = doStuff(item);
if(endEarly)
{
break;
}
}
這裏是一個更實際的例子
static bool[] list = new int[]{false, false, true, false, true, false};
long LowestElementTrue()
{
ParallelLoopResult result = Parallel.ForEach(list, (element, loopState) =>
{
if(element)
loopState.Break();
}
if(result.LowestBreakIteration.IsNull)
return -1;
else
return result.LowestBreakIteration.Value;
}
不管它如何拆分了工作後總是回到2作爲答案。
假設處理器分派兩個線程來處理這個線程,第一個線程處理元素0-2,第二個線程處理元素3-5。
Thread 1: Thread 2 0, False, continue next 3, False, continue next 1, False, continue next 4, True, Break 2, True, Break 5, Don't process Broke
現在的最低指數突破是從所謂的爲2等等ParallelLoopResult.LowestBreakIteration
會每次都返回2,無事的線程是如何分解,因爲它總是會處理多達數2
這裏一個例子如何如何使用Stop。
static bool[] list = new int[]{false, false, true, false, true, false};
long FirstElementFoundTrue()
{
long currentIndex = -1;
ParallelLoopResult result = Parallel.ForEach(list, (element, loopState, index) =>
{
if(element)
{
loopState.Stop();
//index is a 64 bit number, to make it a atomic write
// on 32 bit machines you must either:
// 1. Target 64 bit only and not allow 32 bit machines.
// 2. Cast the number to 32 bit.
// 3. Use one of the Interlocked methods.
Interlocked.Exchange (ref currentIndex , index);
}
}
return currentIndex;
}
根據它如何分割工作,它會返回2或4作爲答案。
假設處理器分派兩個線程來處理這個線程,第一個線程處理元素0-2,第二個線程處理元素3-5。
Thread 1: Thread 2 0, False, continue next 3, False, continue next 1, False, continue next 4, True, Stop 2, Don't process, Stopped 5, Don't process, Stopped
在這種情況下,它將返回4作爲答案。讓我們看看相同的過程,但如果它處理其他元素而不是0-2和3-5。
Thread 1: Thread 2 0, False, continue next 1, False, continue next 2, True, Stop 3, False, continue next 4, Don't process, Stopped 5, Don't process, Stopped
這一次,它會返回2,而不是4
爲了能夠停止Parallel.ForEach
,你可以使用一個接受ParallelOptions
參數的重載之一,幷包括在這些選項CancellationToken
。
有關更多詳細信息,請參閱Cancellation。
至於暫停,我想不出爲什麼你想這樣做,一般來說。您可能正在尋找一個Barrier(用於協調多個線程之間的工作,也就是說他們都需要在繼續B部分之前完成A部分),但我不認爲您會使用Parallel.ForEach
,因爲你不知道會有多少參與者。
暫停?你爲什麼要暫停它? –
暫停只是一個額外的功能,我想添加,如果有可能的話。我正在編寫一個在cpu和互聯網連接上都很重的程序,並且可以快速填充它,所以暫停可能不會那麼糟糕。我只是要實現停止功能並將未完成的元素列表保存到另一個列表,然後在下次運行時重寫該列表。並從停止的地方繼續。有點像暫停。謝謝。 – bbrez1
如果其中一個答案爲您提供瞭解決方案[您應該將該答案標記爲已接受](http://stackoverflow.com/faq#howtoask)。 –