Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/293.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# CancellationToken.ThrowIfCancellationRequested未引发_C#_Task_Cancellationtokensource_Cancellation Token - Fatal编程技术网

C# CancellationToken.ThrowIfCancellationRequested未引发

C# CancellationToken.ThrowIfCancellationRequested未引发,c#,task,cancellationtokensource,cancellation-token,C#,Task,Cancellationtokensource,Cancellation Token,我已经编写了一个非常简单的应用程序来实现一些基于任务的异步操作 客户端代码调用一个返回任务的方法。我将CancellationToken传递给该方法,但即使在过程中调用CancellationToken.ThrowifcCancellationRequested方法,取消也不会引发OperationCancelledException 如果您想自己测试,可以在此处下载整个解决方案: 代码如下: using System; using System.Threading; using System

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

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

如果您想自己测试,可以在此处下载整个解决方案:

代码如下:

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}%";
        }
    }
}
使用系统;
使用系统线程;
使用System.Threading.Tasks;
使用System.Windows.Forms;
命名空间异步示例
{
公共部分类主窗体:窗体
{
私有常量int totalSeconds=5;
私有布尔开始;
公共表格(
{
this.InitializeComponent();
}
私有异步无效处理按钮\u单击(对象发送方,事件参数e)
{
var cts=新的CancellationTokenSource();
如果(!this.istarted)
{
this.processingButton.Text=“取消”;
this.isStarted=true;
var progressIndicator=新进度(this.ReportProgress);
尝试
{
等待此.ProcessLongRunningOperationAsync(progressIndicator,cts.Token);
MessageBox.Show(“已完成!”);
}
捕获(操作取消异常)
{
MessageBox.Show(“取消!”);
}
这是ResetUI();
}
其他的
{
cts.Cancel();
this.processingButton.Text=“开始”;
this.isStarted=false;
}
}
私有void ResetUI()
{
this.progressBar.Value=0;
this.processingButton.Enabled=true;
this.progressMessageLabel.Text=string.Empty;
this.isStarted=false;
this.processingButton.Text=“开始”;
}
专用任务进程LongRunningOperationAsync(IProgress progress,CancellationToken ct)
{
返回任务。运行(
() =>
{

对于(var i=0;i每次调用
processingButton\u单击
,您都会创建
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;
    }
}
private CancellationTokenSource cts;//MainForm实例字段
私有异步无效处理按钮\u单击(对象发送方,事件参数e)
{
如果(!this.istarted)
{
this.cts=新的CancellationTokenSource();
this.processingButton.Text=“取消”;
this.isStarted=true;
var progressIndicator=新进度(this.ReportProgress);
尝试
{
等待此.ProcessLongRunningOperationAsync(progressIndicator,this.cts.Token);
MessageBox.Show(“已完成!”);
}
捕获(操作取消异常)
{
MessageBox.Show(“取消!”);
}
这是ResetUI();
}
其他的
{
this.cts.Cancel();
this.processingButton.Text=“开始”;
this.isStarted=false;
}
}

我现在明白我的错误了。我已经在GitHub上更新了我的项目:非常感谢您的帮助!