Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to reset a CancellationToken properly?

I have been playing round with the Async CTP this morning and have a simple program with a button and a label. Click the button and it starts updating the label, stop the button it stops writing to the label. However, I'm not sure how to reset the CancellationTokenSource so that I can restart the process.

My code:

public partial class MainWindow : Window {     CancellationTokenSource cts = new CancellationTokenSource();     public MainWindow()     {         InitializeComponent();         button.Content = "Start";     }      async Task DoWork(CancellationToken cancelToken)     {         int i = 0;         while (!cancelToken.IsCancellationRequested)         {             label.Content = i++.ToString();             await TaskEx.Delay(50, cancelToken);         }     }      private void Button_Click(object sender, RoutedEventArgs e)     {         if (button.Content == "Start")         {             button.Content = "Stop";             DoWork(cts.Token);         }         else         {             button.Content = "Start";             cts.Cancel();         }     } } 
like image 532
poco Avatar asked Feb 17 '12 17:02

poco


People also ask

Can a CancellationTokenSource be reused?

CancellationTokenSource is quite a heavyweight object and its not normally cancelled; however it can't be pooled or reused because its registrations cannot be cleared.

Does disposing a CancellationTokenSource cancel it?

The Dispose method leaves the CancellationTokenSource in an unusable state. After calling Dispose , you must release all references to the CancellationTokenSource so the garbage collector can reclaim the memory that the CancellationTokenSource was occupying.

How do I cancel a CancellationToken?

A CancellationToken can only be created by creating a new instance of CancellationTokenSource . CancellationToken is immutable and must be canceled by calling CancellationTokenSource. cancel() on the CancellationTokenSource that creates it. It can only be canceled once.

What is CancellationToken in .NET core?

So CancellationToken can be used to terminate a request execution at the server immediately once the request is aborted or orphan. Here we are going to see some sample code snippets about implementing a CancellationToken for Entity FrameworkCore, Dapper ORM, and HttpClient calls in Asp. NetCore MVC application.


Video Answer


2 Answers

You need to recreate the CancellationTokenSource - there is no way to "reset" this once you set it.

This could be as simple as:

private void Button_Click(object sender, RoutedEventArgs e) {     if (button.Content == "Start")     {         button.Content = "Stop";         cts.Dispose(); // Clean up old token source....         cts = new CancellationTokenSource(); // "Reset" the cancellation token source...         DoWork(cts.Token);     }     else     {         button.Content = "Start";         cts.Cancel();     } } 
like image 71
Reed Copsey Avatar answered Sep 19 '22 18:09

Reed Copsey


I had the same problem and I figured it out that the best way to solve it is to create cancellation token source newly just before calling the method.

this is what I do on my start button click:

cancellationTokenSource = new CancellationTokenSource(); cancellationToken = cancellationTokenSource.Token; Task.Factory.StartNew(StartUpload, cancellationToken); 

I change the caption for the same button to cancel and when a click occurs on cancel, I call

cancellationTokenSource.Cancel(); 

Here is the full code:

if (button3.Text != "&Start Upload") {     cancellationTokenSource.Cancel(); } else {     try     {         cancellationTokenSource = new CancellationTokenSource();         cancellationToken = cancellationTokenSource.Token;         Task.Factory.StartNew(StartUpload, cancellationToken);     }     catch (AggregateException ex)     {         var builder = new StringBuilder();         foreach (var v in ex.InnerExceptions)             builder.Append("\r\n" + v.InnerException);         MessageBox.Show("There was an exception:\r\n" + builder.ToString());     }     catch (Exception ex)     {         MessageBox.Show(ex.Message);     } } 
like image 22
Amit Avatar answered Sep 21 '22 18:09

Amit