Search code examples
c#task-parallel-library.net-4.5cancellation-token

CancellationToken doesn't cancel blocking method


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.


Solution

  • 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.