76 votes

Comment réinitialiser correctement un CancellationToken ?

J'ai joué avec le Async CTP ce matin et j'ai un programme simple avec un button et un label . Cliquez sur le button et il commence à mettre à jour le label , arrêtez le button il arrête d'écrire sur le label . Cependant, je ne sais pas comment réinitialiser le CancellationTokenSource afin de pouvoir redémarrer le processus.

Mon 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();
        }
    }
}

111voto

Reed Copsey Points 315315

Vous devez recréer le CancellationTokenSource - il n'y a aucun moyen de le "réinitialiser" une fois que vous l'avez défini.

Cela peut être aussi simple que :

 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();
    }
}

10voto

Amit Points 2733

J'ai eu le même problème et j'ai compris que la meilleure façon de le résoudre était de créer une nouvelle source de jeton d'annulation juste avant d'appeler la méthode.

c'est ce que je fais sur mon clic sur le bouton de démarrage:

 cancellationTokenSource = new CancellationTokenSource();
cancellationToken = cancellationTokenSource.Token;
Task.Factory.StartNew(StartUpload, cancellationToken);

Je change la légende du même bouton pour annuler et lorsqu'un clic se produit sur annuler, j'appelle

 cancellationTokenSource.Cancel();

Voici le code complet :

 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);
    }
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X