Как правильно сбросить CancellationToken?

Сегодня утром я играл с Async CTP и у меня есть простая программа с button и label. Нажмите button, и он начнет обновлять label, остановите button, он перестанет записывать в label. Однако я не знаю, как сбросить CancellationTokenSource, чтобы перезапустить процесс.

Мой код:

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

person poco    schedule 17.02.2012    source источник


Ответы (2)


Вам нужно воссоздать CancellationTokenSource - нет возможности «сбросить» это после того, как вы его установили.

Это может быть так же просто, как:

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();
    }
}
person Reed Copsey    schedule 17.02.2012
comment
Когда вы должны избавиться от него при закрытии приложения? Поскольку вам нужно подождать, пока поток не будет выполнен, иначе вы получите исключение ObjectDisposed. - person Zerowalker; 25.08.2013
comment
@user2587718 user2587718 Это действительно зависит от типа объекта и т. Д. Я бы рекомендовал задать свой вопрос по этому поводу. - person Reed Copsey; 26.08.2013
comment
Должен действительно сделать нулевую проверку перед удалением, но это было хорошо, поскольку это именно то, что я делаю. - person Louis Duran; 21.04.2018
comment
Пытаясь узнать немного больше о CancellationTokens, почему вы не избавляетесь от cts сразу после вызова Cancel? Должен ли он быть утилизирован только в следующий раз, когда он будет обновлен? - person user1; 06.12.2019

У меня была та же проблема, и я понял, что лучший способ решить ее — создать новый источник токена отмены непосредственно перед вызовом метода.

это то, что я делаю при нажатии кнопки «Пуск»:

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

Я меняю заголовок для той же кнопки на отмену, и когда происходит щелчок по отмене, я вызываю

cancellationTokenSource.Cancel();

Вот полный код:

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);
    }
}
person Amit    schedule 04.12.2013