Reputation: 4586
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'.
Upvotes: 4
Views: 6274
Reputation: 1578
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:
Compute()
methodOperationCanceledException
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();
}
}
Upvotes: 3
Reputation: 61744
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();
Upvotes: 0