Reputation: 20745
I am calling some code in Parallel.Foreach()
. The code has Thread.Sleep(60000)
, so if I cancel the token also then it waits for 60 seconds before cancelling the Parallel.ForEach loop.
Thread.Sleep()
is put in this code for explanation. The actual code has some code that waits for other resources.
I want to cancel all activity as cts.Cancel();
is called.
I tried LoopState also but it will not work in my case.
using System;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
class Program
{
static void Main()
{
int[] nums = Enumerable.Range(0, 10000000).ToArray();
CancellationTokenSource cts = new CancellationTokenSource();
// Use ParallelOptions instance to store the CancellationToken
ParallelOptions po = new ParallelOptions();
po.CancellationToken = cts.Token;
po.MaxDegreeOfParallelism = System.Environment.ProcessorCount;
Console.WriteLine("Press any key to start. Press 'c' to cancel.");
Console.ReadKey();
// Run a task so that we can cancel from another thread.
Task.Factory.StartNew(() =>
{
if (Console.ReadKey().KeyChar == 'c')
{
cts.Cancel();
}
Console.WriteLine("press any key to exit");
});
try
{
Parallel.ForEach(nums, po, (num) =>
{
double d = Math.Sqrt(num);
Console.WriteLine("{0} on {1}", d, Thread.CurrentThread.ManagedThreadId);
Thread.Sleep(60000); //Thread Sleep for 1 minute
po.CancellationToken.ThrowIfCancellationRequested();
});
}
catch (OperationCanceledException e)
{
Console.WriteLine(e.Message);
}
finally
{
cts.Dispose();
}
Console.ReadKey();
}
}
Upvotes: 1
Views: 2026
Reputation: 70671
If I understand correctly, it is not really that you need to interrupt the thread immediately, but rather that you simply want to be able to interrupt the Sleep()
method while it's waiting.
There are a number of options, but one of the simplest IMHO is to use the CancellationToken.WaitHandle
property value, and wait on that instead of sleeping:
po.CancellationToken.WaitHandle.WaitOne(60000);
If the token is signaled, the Wait()
method will return before the timeout specified (one minute in this case).
Typically you'd check the return value, so you can tell the difference between the handle being signaled and the wait timing out, but in your case you immediately call po.CancellationToken.ThrowIfCancellationRequested();
, so it seems reasonable to me to just ignore the return value from the Wait()
method and let the next program statement take care of actually interrupting the method.
Upvotes: 2