2013-02-06 270 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()从头开始停止任何新的循环迭代,并等待当前正在运行的任何完成循环。