Wie setze ich ein CancellationToken richtig zurück?
-
27-10-2019 - |
Frage
Ich habe heute Morgen mit dem async ctp
herumgespielt und habe ein einfaches Programm mit einem button
und einem label
.Klicken Sie auf den button
und der label
wird aktualisiert. Stoppen Sie den button
, der nicht mehr in den label
geschrieben wird.Ich bin mir jedoch nicht sicher, wie ich den CancellationTokenSource
zurücksetzen soll, damit ich den Prozess neu starten kann.Mein Code ist unten:
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();
}
}
}
Lösung
Sie müssen den CancellationTokenSource
neu erstellen - es gibt keine Möglichkeit, diesen nach dem Festlegen zurückzusetzen.
Dies kann so einfach sein wie:
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();
}
}
Andere Tipps
Sogar ich hatte das gleiche Problem und habe herausgefunden, dass der beste Weg, es zu lösen, darin besteht, eine Quelle für das Lösch-Token kurz vor dem Aufruf der Methode neu zu erstellen.
Dies ist, was ich mache, wenn ich auf die Schaltfläche "Start" klicke:
cancellationTokenSource = new CancellationTokenSource();
cancellationToken = cancellationTokenSource.Token;
Task.Factory.StartNew(StartUpload, cancellationToken);
Ich ändere die Beschriftung für dieselbe Schaltfläche, um abzubrechen, und wenn ein Klick auf Abbrechen auftritt, rufe ich an
cancellationTokenSource.Cancel();
Hier ist der vollständige 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);
}
}