立即取消C#Parallel.Foreach的所有正在运行的线程

时间:2013-12-24 05:02:19

标签: c# multithreading c#-4.0 task-parallel-library backgroundworker

我正在使用Multithreading来解决我的问题。我一直在后台工作程序Parallel.Foreach事件中使用DoWork,其中长时间运行的作业一直在执行。但是,当我必须取消这项工作时,问题就出现了。它不会立即取消线程。

BackgroundWorker DoWork活动:

private void File_DoWork(object sender, DoWorkEventArgs e)
{
    var cts = new CancellationTokenSource();
    btnCancel.Click += (cancelSender, cancelEvent) =>
                {
                     bgwFile.CancelAsync();

                     if (bgwFile.CancellationPending)
                     {
                         cts.Cancel();
                         e.Cancel = true;
                     }
                };
    object sync = new object();
    List<Response> responses = null;

    var parallelOperation = new ParallelOptions
    {
          MaxDegreeOfParallelism = 3,
          CancellationToken = cts.Token
    };

    Parallel.ForEach(listRequest, parallelOperation, request =>
    {
        lock (sync)
        {
             responses = GetQueryResponse(request); // Long running process      
             parallelOperation.CancellationToken.ThrowIfCancellationRequested();
        }
    });
    e.Result = responses ;
}

这里,问题是我必须取消长时间运行的工作。假设有三个请求已经循环并行。有MaxDegreeOfParallelism = 3,然后它用于GetQueryResponse(request)方法,这是一个很长的工作,如果我使用CancellationTokenSource取消线程,那么它不会立即取消该过程。它只在执行3个请求线程后取消。

我希望立即取消它。是否有任何方法可以立即取消由Parallel.Foreach生成的所有正在运行的线程并转到后台工作的RunWorkerCompleted事件?

3 个答案:

答案 0 :(得分:3)

您可以使用CancellationToken.Register Method (Action) 注册在取消CancellationToken时将被调用的代理。

请求取消后会立即解雇。当然,您必须编写将立即导致当前GetQueryResponse执行停止的逻辑。

答案 1 :(得分:0)

检查TPL的CancellationTokens。here将CancellationToken传递给Parallel.Foreach()可以使它工作。当您想要停止所有任务时,只需使用:

cts.Cancel()

在Task的方法位置

cts.Token.ThrowIfCancellationRequested(); 当你想检查是否需要停止任务,因为另一个任务取消了该过程。

答案 2 :(得分:-2)

您可以将线程的IsBackground属性设置为true。当你的应用程序完成时,这将终止所有线程。

您可以使用一个定时器(或一个线程)来唤醒并检查数据。这应该更加资源友好。