¿Cómo reinicio correctamente un CancellationToken?
-
27-10-2019 - |
Pregunta
He estado jugando con el async ctp
esta mañana y tener un programa simple con un button
y un label
. Haga clic en el button
y comienza a actualizar el label
, para el button
Deja de escribir para el label
. Sin embargo, no estoy seguro de cómo reiniciar el CancellationTokenSource
para que pueda reiniciar el proceso. Mi código está a continuación:
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();
}
}
}
Solución
Necesitas recrear el CancellationTokenSource
- No hay forma de "reiniciar" esto una vez que lo establece.
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();
}
}
Otros consejos
Incluso tuve el mismo problema y lo descubrí que, la mejor manera de resolverlo es crear una fuente de token de cancelación recién antes de llamar al método.
Esto es lo que hago en mi botón de inicio, clic:
cancellationTokenSource = new CancellationTokenSource();
cancellationToken = cancellationTokenSource.Token;
Task.Factory.StartNew(StartUpload, cancellationToken);
Cambio el subtítulo para que el mismo botón cancele y cuando se produce un clic en 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);
}
}