【问题标题】:CancellationToken.ThrowIfCancellationRequested not throwingCancellationToken.ThrowIfCancellationRequested 不抛出
【发布时间】:2015-09-12 21:04:47
【问题描述】:

我编写了一个非常简单的应用程序来实现一些基于任务的异步操作。

客户端代码调用一个返回任务的方法。我将 CancellationToken 传递给该方法,但即使我在此过程中调用 CancellationToken.ThrowIfCancellationRequested 方法,取消也不会抛出 OperationCancelledException。

如果您想自己测试,可以在此处下载整个解决方案: https://github.com/stevehemond/asynctap-example

代码如下:

using System;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace AsyncTapExample
{
    public partial class MainForm : Form
    {
        private const int totalSeconds = 5;

        private bool isStarted;

        public MainForm()
        {
            this.InitializeComponent();
        }

        private async void processingButton_Click(object sender, EventArgs e)
        {
            var cts = new CancellationTokenSource();

            if (!this.isStarted)
            {
                this.processingButton.Text = "Cancel";

                this.isStarted = true;

                var progressIndicator = new Progress<int>(this.ReportProgress);

                try
                {
                    await this.ProcessLongRunningOperationAsync(progressIndicator, cts.Token);

                    MessageBox.Show("Completed!");
                }
                catch (OperationCanceledException)
                {
                    MessageBox.Show("Cancelled!");
                }

                this.ResetUI();
            }
            else
            {
                cts.Cancel();
                this.processingButton.Text = "Start";
                this.isStarted = false;
            }
        }

        private void ResetUI()
        {
            this.progressBar.Value = 0;
            this.processingButton.Enabled = true;
            this.progressMessageLabel.Text = string.Empty;
            this.isStarted = false;
            this.processingButton.Text = "Start";
        }

        private Task ProcessLongRunningOperationAsync(IProgress<int> progress, CancellationToken ct)
        {
            return Task.Run(
                () =>
                    {
                        for (var i = 0; i <= totalSeconds; i++)
                        {
                            ct.ThrowIfCancellationRequested();

                            Thread.Sleep(1000);
                            progress?.Report((i * 100) / totalSeconds);
                        }
                    },
                ct);
        }

        private void ReportProgress(int progressPercentage)
        {
            this.progressBar.Value = progressPercentage;
            this.progressMessageLabel.Text = $"{progressPercentage}%";
        }
    }
}

关于将 CancellationToken 传递给 Tasks 一定有什么我不明白的地方……我就是不知道是什么。

【问题讨论】:

    标签: c# task cancellationtokensource cancellation-token


    【解决方案1】:

    您在每次调用processingButton_Click 时创建CancellationTokenSource。结果,您取消了与用于创建任务的 CancellationTokenSource 不同的 CancellationTokenSource。只有在创建新任务时才应该创建新的CancellationTokenSource,并且应该保存CancellationTokenSource,以便取消它:

    private CancellationTokenSource cts; //MainForm instance field
    
    private async void processingButton_Click(object sender, EventArgs e)
    {
        if (!this.isStarted)
        {
            this.cts = new CancellationTokenSource();
    
            this.processingButton.Text = "Cancel";
    
            this.isStarted = true;
    
            var progressIndicator = new Progress<int>(this.ReportProgress);
    
            try
            {
                await this.ProcessLongRunningOperationAsync(progressIndicator, this.cts.Token);
    
                MessageBox.Show("Completed!");
            }
            catch (OperationCanceledException)
            {
                MessageBox.Show("Cancelled!");
            }
    
            this.ResetUI();
        }
        else
        {
            this.cts.Cancel();
            this.processingButton.Text = "Start";
            this.isStarted = false;
        }
    }
    

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-11-26
    • 2015-12-30
    • 1970-01-01
    • 2013-02-12
    • 1970-01-01
    • 2022-06-11
    • 2016-10-05
    • 1970-01-01
    相关资源
    最近更新 更多