How to reset a CancellationToken properly?
Solution 1
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();
}
}
Solution 2
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);
}
}
Solution 3
Now, with .NET 6 you can use TryReset()
method which Attempts to reset the CancellationTokenSource to be used for an unrelated operation.
see this issue and CancellationTokenSource.cs for more details.
poco
Updated on July 05, 2022Comments
-
poco almost 2 years
I have been playing round with the
Async CTP
this morning and have a simple program with abutton
and alabel
. Click thebutton
and it starts updating thelabel
, stop thebutton
it stops writing to thelabel
. However, I'm not sure how to reset theCancellationTokenSource
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(); } } }
-
Zerowalker over 10 yearsWhen are you supposed to dispose of it on close of the application? As you have to wait before the Thread is done, else you get ObjectDisposed exception.
-
Reed Copsey over 10 years@user2587718 It really depends on what type of object, etc. I'd recommend asking your own question regarding this.
-
Louis Duran about 6 yearsShould really do a null check before disposing but this was good since it is exactly what I am doing.
-
User1 over 4 yearsTrying to learn abit more about CancellationTokens, Why are you not disposing of the cts straight after the
Cancel
call? Should it only be disposed of the next time it is about to be newed up?