Reputation: 7517
It appears, I can't cancel a blocking method running inside a task using the CancellationTokenSource
built-in timeout.
class Program
{
static void Main(string[] args)
{
var cts = new System.Threading.CancellationTokenSource();
System.Console.CancelKeyPress += (s, e) =>
{
e.Cancel = true;
cts.Cancel();
};
MainAsync(args, cts.Token).Wait();
}
// MainAsync from http://stackoverflow.com/questions/9208921/async-on-main-method-of-console-app
static async Task MainAsync(string[] args, System.Threading.CancellationToken token)
{
Console.WriteLine("Starting MainAsync");
var cts = new System.Threading.CancellationTokenSource(3000);
var task = Task.Factory.StartNew(() =>
{
Console.WriteLine("Starting task...");
var t = new System.Net.Sockets.TcpClient();
var buffer = new byte[t.ReceiveBufferSize];
t.Connect(new System.Net.IPEndPoint(System.Net.IPAddress.Parse("127.0.0.1"), 1337));
Console.WriteLine("Recieving...");
t.Client.Receive(buffer);
Console.WriteLine("Finished Recieving...");
return true;
}, cts.Token);
var success = await task;
Console.WriteLine("Did the task complete succesfuly?", success);
}
}
The output from the above Short, Self Contained, Correct Example (I hope it's correct) is:
Starting MainAsync
Starting task...
Recieving...
Why does the task doesn't cancel, no exception is thrown?
I am using .NET Framework 4.5.1.
Upvotes: 9
Views: 2124
Reputation: 6580
I am not sure but I guess you are confusing "requesting a cancellation" with "terminating or aborting a thread/task". These are two completely different things. According to the description about the Cancellation in Managed Threads the provided functionality enables you to send something like a signal, indicating, that the operation in progress shall be stopped.
How and if you react on that signal is - as a programmer - up to you.
In your example you've started a new task
var task = Task.Factory.StartNew(() =>
{
Console.WriteLine("Starting task...");
var t = new System.Net.Sockets.TcpClient();
var buffer = new byte[t.ReceiveBufferSize];
t.Connect(new System.Net.IPEndPoint(System.Net.IPAddress.Parse("127.0.0.1"), 1337));
Console.WriteLine("Recieving...");
t.Client.Receive(buffer);
Console.WriteLine("Finished Recieving...");
return true;
}, cts.Token);
which does not handle the cancellation nor is it suitable to do so.
Cancellation would be used e.g. if you want to break out of a loop with many iterations - therefore you would check in each iteration whether the CancellationToken.IsCancellationRequested
has been set to true or not.
If so, you can react accordingly.
What you want is to abort the thread that's behind the current task which is in my opinion only possible by creating a new instance of the Thread
class for yourself and handle the abort accordingly.
Upvotes: 3
Reputation: 456507
As I state on my blog, "You keep using that CancellationToken
there. I do not think it means what you think it means."
In particular, the CancellationToken
passed to StartNew
will only cancel the starting of the delegate. If you want the delegate itself to support cancellation, then the delegate itself will have to observe the CancellationToken
.
Upvotes: 8