暂停和恢复Parallel.ForEach

时间:2013-12-12 04:57:24

标签: c#

    private bool isProcessing=false;
    public bool IsProcessing { get { return isProcessing; } }

    private bool IsTerminated=false;

    private bool isPaused=false;
    public bool IsPaused { get { return isPaused; } }

此函数包含Parallel.ForEach

private void StartProcess()
        {
            isPaused = IsTerminated = false;
            isProcessing = true;

            Parallel.ForEach(items, new ParallelOptions() { MaxDegreeOfParallelism = 4 }, (item, state) =>
                {
                    if (isPaused) state.Stop();
                    if (IsTerminated) state.Break();
                    item.Process();
                });

            isPaused = IsTerminated = false;
            isProcessing = false;
        }

考虑以下情况,调用StartProcess(),然后将IsTerminated设置为true,循环中断,当isPaused设置为true时同样发生,我不知道如何在调用Stop()后恢复Parallel.ForEach ,我怎么能得到每个线程已经开始和停止的位置的索引?

在暂停/恢复的情况下,我通过向项目对象添加一个布尔值来指示它是否被处理, 然后继续再次调用StartProcess()并跳过已处理的项目,但我确信有更好的方法,我不需要自定义我的对象结构,另一种方法是添加处理过的项目引用列表并在简历中跳过它们

2 个答案:

答案 0 :(得分:1)

似乎你需要

http://msdn.microsoft.com/en-us/library/dd267312(v=vs.110).aspx

如果计算机有4个核心,则创建4个线程。

答案 1 :(得分:1)

您需要从ParallelLoopResult电话中获取Parallel.ForEach。它会告诉你哪个是最后处理的元素。

此外,您似乎向后Stop()Break()Stop()会尽快停止,您处理的最后一个项目下方的某些项目可能尚未处理。 Break()会尽快停止,但会继续处理,直到处理完当前项目之前的所有项目,然后报告上次处理的项目的索引。

   private long? lowestBreakIndex = null;

    private void StartProcess()
    {
        isPaused = IsTerminated = false;
        isProcessing = true;

        ParallelLoopResult result = Parallel.ForEach(
            items.Skip(lowestBreakIndex ?? 0) //I am assuming that items is some form of ICollection. The Skip function will skip to the next item to process
            , new ParallelOptions() { MaxDegreeOfParallelism = 4 }, (item, state) =>
            {
                //I swapped these two.
                if (isPaused) 
                    state.Break();
                else if (IsTerminated) 
                    state.Stop();
                else
                    item.Process();
            });

        lowestBreakIndex = result.LowestBreakIteration;

        isPaused = IsTerminated = false;
        isProcessing = false;
    }

重要提示:您可能会运行两次相同的项目。请注意,如果两个线程都报告了中断,则两个线程中的较低者将是报告结果的人。

有关Stop()Break()的详细信息,请参阅另一个有关Parallel.ForEach的问题的this old answer of mine