Eugene Petrov
Eugene Petrov

Reputation: 651

Multithreading - don't understand the situation

        var tokenSource2 = new CancellationTokenSource();
        CancellationToken ct = tokenSource2.Token;

        var task = Task.Factory.StartNew(() => { 
                     Thread.Sleep(4000);
                     Console.WriteLine("Done");
                     ct.ThrowIfCancellationRequested(); 
                   }, ct);

        Thread.Sleep(1000); Look here! <--- 
        tokenSource2.Cancel();

        try
        {
            Console.WriteLine("Wait");
            task.Wait();
        }
        catch (Exception e)
        {
            Console.WriteLine("Task was canceled");
        }

I can't understand why if I comment this line all works ok and exception is catched in the main thread, but if I left this line exception is thrown in child thread on the line with ct.ThrowIfCancellationRequested(); We have one instance of the cancelation token in both cases. I'm a new in multithreadin, so I definetly miss somthing.

I tried the next code

    static void Main(string[] args)
    {
        Thread.CurrentThread.Name = "Main";

        Console.WriteLine("Name of the current thread is " + Thread.CurrentThread.Name);

        var tokenSource2 = new CancellationTokenSource();
        CancellationToken ct = tokenSource2.Token;
        var task = Task.Factory.StartNew(() => 
        { 
            Thread.Sleep(4000); 
            Console.WriteLine("Done");

            try
            {
                ct.ThrowIfCancellationRequested(); // If I remove the try/catch here will be unhandled exception
            }
            catch (OperationCanceledException exp)
            {
                Console.WriteLine("Task was started then canceled");   
            }

        }, ct);//ontinueWith(OnProcessImageEnded);

        Thread.Sleep(1000);
        tokenSource2.Cancel();

        try
        {
            Console.WriteLine("Wait");
            task.Wait();
        }
        catch (Exception e)
        {
            Console.WriteLine("Task was canceled");
        }

        Console.WriteLine("Task was finished");

        Console.WriteLine(task.Status);

I process exception in the task's thread now, but it leads to Status of the task not to be set Canceled. I think it is because now the task can't catch the exception to process it. What is the right way?

I found http://msdn.microsoft.com/en-us/library/ee191553.aspx this example and it has the same problem! if we press on 'c' during execution it will throws unhandled exception when we try to rethrow by calling externalToken.ThrowIfCancellationRequested(); ... I'm confused at all. I'm using x64 Win 7, 4.5 .net framework

Upvotes: 2

Views: 184

Answers (2)

YK1
YK1

Reputation: 7602

When you comment the line, chances are our Task is cancelled even before it is started. Hence you get the exception. When you add sleep - mostly it will be started, so cancellation happens within the task with your call to ThrowIfCancellationRequested

Upvotes: 2

ChaosPandion
ChaosPandion

Reputation: 78242

I'll defer to the documentation for this one.

Task.Wait Method

AggregateException

The Task was canceled -or- an exception was thrown during the execution of the Task. If the task was canceled, the AggregateException contains an OperationCanceledException in its InnerExceptions collection.

Essentially it is a race condition where if you make it to task.Wait in time you win.

Upvotes: 0

Related Questions