ThrowIfCancellationRequested doesn't seem to throw any exceptions

混江龙づ霸主 提交于 2019-12-04 03:58:05

问题


I have the following code :

CancellationTokenSource cts = new CancellationTokenSource();
ParallelOptions po = new ParallelOptions();
po.CancellationToken = cts.Token;

Task.Factory.StartNew(() =>
{
     if (Console.ReadKey().KeyChar == 'c')
         cts.Cancel();
     Console.WriteLine("press any key to exit");
});

 Parallel.ForEach(list, po, (algo) =>
 {
      algo.Compute(); // this compute lasts 1 minute  
      Console.WriteLine("this job is finished");       
      po.CancellationToken.ThrowIfCancellationRequested();
 });

The list contains few elements. All the Compute methods have already been started when I press 'c'.

When I press 'c', no exception is thrown. Each Compute methods continues its execution until its normal end.

I would like to stop/kill all the remain Compute methods when I press 'c'.


回答1:


Cancellation doesn't work like that. It's not like calling Thread.Abort() to terminate thread immediately.

For each element in a sequence your code does:

  1. Calls Compute() method
  2. Waits until its completion
  3. Writes to console about finish
  4. Checks if cancellation was requested and throw the OperationCanceledException if it was.

In order to cancel some task you need to pass the CancellationToken to the called method.
Perhaps, it's worth organizing your long running computations as a cycle and check if cancellation were requested at each step in order to stop it ASAP.

For example, in your Compute() method you could perform check like this:

private void Compute(CancellationToken ct)
{
    while (true)
    {
       ComputeNextStep();
       ct.ThrowIfCancellationRequested();
    }
}



回答2:


Observe the cancellation with po.CancellationToken.IsCancellationRequested and use ParallelLoopState.Stop to stop Parallel.ForEach:

void Compute(CancellationToken token, ParallelLoopState loopState)
{
    bool more = true;
    while (more)
    {
        if (token.IsCancellationRequested)
        {
            // stop Parallel.ForEach ASAP
            loopState.Stop();
            return;
        }
        // do the calc step
    }
}

// ... 

CancellationTokenSource cts = new CancellationTokenSource();
ParallelOptions po = new ParallelOptions();
po.CancellationToken = cts.Token;

Task.Factory.StartNew(() =>
{
    if (Console.ReadKey().KeyChar == 'c')
        cts.Cancel();
    Console.WriteLine("press any key to exit");
});

Parallel.ForEach(list, po, (algo, loopState) =>
{
    algo.Compute(po.CancellationToken, loopState); // this compute lasts 1 minute  
    Console.WriteLine("this job is finished");
});
// observe the cancellation again and throw after Parallel.ForEach
po.CancellationToken.ThrowIfCancellationRequested();


来源:https://stackoverflow.com/questions/22530757/throwifcancellationrequested-doesnt-seem-to-throw-any-exceptions

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!