gpt4 book ai didi

c# - Parallel.Foreach c# 暂停和停止功能?

转载 作者:太空狗 更新时间:2023-10-29 22:16:55 25 4
gpt4 key购买 nike

暂停和停止(结束前)parallel.foreach 的最有效方法是什么?

Parallel.ForEach(list, (item) =>
{
doStuff(item);
});

最佳答案

Damien_The_Unbeliver有一个很好的方法,但只有当你想让一些外部进程停止循环时才会这样。如果你想像在普通的 forforeach 循环中使用 break 一样中断循环,你将需要使用 a overload有一个 ParallelLoopState作为循环体的参数之一。 ParallelLoopState 有两个与您想要执行的操作相关的函数,Stop()Break() .

Stop() 函数将在系统方便时尽早 停止处理元素,这意味着在您调用 Stop() 后可能会执行更多迭代,但不保证在您停止的元素之前出现的元素甚至已经开始处理。

函数 Break() 的执行与 Stop() 完全相同,但是它还会评估之前出现的 IEnumerable 的所有元素您调用 Break() 的项目。当您不关心元素的处理顺序,但必须处理所有元素直到停止点时,这很有用。

检查 ParallelLoopResult从 foreach 返回以查看 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 作为答案。

假设处理器分派(dispatch)两个线程来处理它,第一个线程处理元素 0-2,第二个线程处理元素 3-5。

Thread 1:                Thread 20, False, continue next  3, False, continue next1, False, continue next  4, True, Break2, True, Break           5, Don't process Broke

Now the lowest index Break was called from was 2 so ParallelLoopResult.LowestBreakIteration will return 2 every time, no-matter how the threads are broken up as it will always process up to the number 2.

Here an example how how Stop could be used.

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 作为答案。

假设处理器分派(dispatch)两个线程来处理它,第一个线程处理元素 0-2,第二个线程处理元素 3-5。

Thread 1:                 Thread 20, False, continue next    3, False, continue next1, False, continue next    4, True, Stop2, Don't process, Stopped  5, Don't process, Stopped

在这种情况下,它将返回 4 作为答案。让我们看看相同的过程,但如果它处理所有其他元素而不是 0-2 和 3-5。

Thread 1:                   Thread 20, False, continue next     1, False, continue next2, True, Stop               3, False, continue next4, Don't process, Stopped   5, Don't process, Stopped

这次它将返回 2 而不是 4。

关于c# - Parallel.Foreach c# 暂停和停止功能?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8461430/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com