如何从主线程中杀死Parallel.ForEach生成的所有线程?

时间:2011-05-19 01:01:51

标签: c# multithreading .net-4.0 kill plinq

以下是该方案:

我有正在运行的Windows服务。 OnStart()它会设置一个调用函数的计时器(让我们称之为ProcessEvent())。 ProcessEvent中的代码是一个关键部分,因此只有一个线程可以执行以下操作:

private void ProcessEvent(object sender, ElapsedEventArgs e)
{
    lock(lockObj)
    {
        string[] list = GetList();
        Parallel.ForEach(list, item => { ProcessItem(item) });
    }
}

ProcessItem可能需要很长时间。

现在当服务停止时,OnStop()当前只是停止并处理计时器。但是我注意到,即使服务停止后,仍有一些线程仍在运行ProcessItem()

那么如何杀死这个程序产生的所有正在运行的线程(主要是Parallel.ForEach产生的线程,还有等待ProcessEvent锁定的任何线程?)

我知道如果我自己创建了线程,我可以将isBackground设置为true,当进程死亡时它们都会被杀死但我不会手动创建这些线程。

2 个答案:

答案 0 :(得分:8)

使用CancellationToken结构。有关详细信息,请阅读thisthis

// Setup the cancellation mechanism.
var cts = new CancellationTokenSource();
var po = new ParallelOptions();
po.CancellationToken = cts.Token;

// Run the enumerator in parallel.
Parallel.ForEach(list, po, 
  (item) =>
  {
    ProcessItem(item);
    po.CancellationToken.ThrowIfCancellationRequested();
  });

// Call Cancel to make Parallel.ForEach throw.
// Obviously this must done from another thread.
cts.Cancel();

答案 1 :(得分:5)

查看带有Parallel.ForEach参数的委托的ParallelLoopState重载。检查正文中的标志,看看是否应继续执行,否则将其删除:

Parallel.ForEach(list, (item, pls) => { 
    if(quit)pls.Stop();
    else
        ProcessItem(item);
});