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();
        }
    }
}
¿Fue útil?

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);
            }
        }
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top