c# - run - ¿Cómo reinicio un CancellationToken correctamente?
cancellationtoken c# (2)
He estado jugando con el async ctp
esta mañana y tengo un programa simple con un button
y una label
. Haga clic en el button
y comienza a actualizar la label
, detenga el button
que deja de escribir en la label
. Sin embargo, no estoy seguro de cómo restablecer el CancellationTokenSource
para que pueda reiniciar el proceso. Mi código está abajo:
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();
}
}
}
Incluso tuve el mismo problema y me di cuenta de que la mejor forma de resolverlo es crear una fuente de token de cancelación justo antes de llamar al método.
esto es lo que hago en mi botón de inicio, haga clic en:
cancellationTokenSource = new CancellationTokenSource();
cancellationToken = cancellationTokenSource.Token;
Task.Factory.StartNew(StartUpload, cancellationToken);
Cambio el título del mismo botón para cancelar y cuando se produce un clic al cancelar, llamo
cancellationTokenSource.Cancel();
Aquí está el código completo:
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);
}
}
Necesitas recrear el CancellationTokenSource
- no hay forma de "reiniciar" esto una vez que lo estableces.
Esto podría ser tan simple como:
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();
}
}