0

This question has already been asked but I still don't get it... I'm trying to cancel a task but when I include ThrowIfCancellationRequested(), it is not catched and if I don't include it, the GUI freezes...

Here is my code that run without the ThrowIfCancellationRequested() but freeze the GUI:

 public void StartProcess(double myvariable)
    {
        tokenSource = new CancellationTokenSource();
        CancellationToken token = tokenSource.Token;

        processThread = Task.Factory.StartNew(() =>
        {
            while (true)
            {
                //Do some work with myvariable

                if (token.IsCancellationRequested)
                {
                    break;
                }
            }
        }, token);
    }

And the code with the ThrowIfCancellationRequested() that is not catched, the debugger stops on the line token.ThrowIfCancellationRequested():

 public void StartProcess(double myvariable)
    {
        tokenSource = new CancellationTokenSource();
        CancellationToken tokenDispatcher = tokenSource.Token;

        processThread = Task.Factory.StartNew(() =>
        {
            try
            {
                while (true)
                {
                    //Do some work with myvariable

                    if (token.IsCancellationRequested)
                    {
                        token.ThrowIfCancellationRequested();
                        break;
                    }
                }
            }
            catch (AggregateException ae)
            {
                    if (ae.InnerException is OperationCanceledException)
                    {
                        Console.WriteLine("Process Thread Cancelled");
                    }
                    else
                    {
                        Console.WriteLine("ERROR");
                    }
            }
        }, token);
    }

What am I doing wrong?

bricx
  • 593
  • 4
  • 18
  • If you call `ThrowIfCancellationRequested` you don’t need to check `IsCancellationRequested` at all. Also you don’t need the `break`. If a cancellation is requested Throw… will throw an exception and never get to your break anyway. If no cancellation is requested Throw… won’t throw and the if-check is unnecessary. – ckuri Feb 16 '19 at 08:26

1 Answers1

1

The ThrowIfCancellationRequested is the proper way to cancel the task. What you need to understand is that there will be no exception when you cancel a Task. Only the Status of the task will be set to Canceled. The try catch block you have inside the task will do nothing. To get an exception you need to await the Task in an async method or use the Wait method to wait for the finish of the task. Using the Wait method is not recommended because you are blocking the current thread until the task finishes.

Here is a suggestion how you could implement this from your code.

public static Task StartProcess(double myvariable)
{
   tokenSource = new CancellationTokenSource();
   CancellationToken token = tokenSource.Token;

   return Task.Factory.StartNew(() =>
   {
      while (true)
      {
         //Do some work with myvariable

         token.ThrowIfCancellationRequested();
      }
   }, token);
}

public async Task ExecuteProcess(double myvariable)
{
   try
   {
      await StartProcess(myvariable);
   }
   catch (OperationCanceledException ex)
   {
      Console.WriteLine("Process Thread Canceled");
   }
   catch (Exception ex)
   {
      Console.WriteLine("ERROR");
   }
}

The ExecuteProcess method demonstrates how you need to call your function to get the exception. This way you also prevent the GUI from blocking if you call the method from the UI thread.

I recommend you read the documentation on asynchronous programming to get more understanding on how it works.

Aleš Doganoc
  • 11,568
  • 24
  • 40
  • You should replace the complete if-block with just `token.ThrowIfCancellationRequested();` which does the same. – ckuri Feb 16 '19 at 08:29