.net - TPL 取消延续从未调用已取消的任务

标签 .net multithreading task-parallel-library task

我的代码中有以下使用 TPL 的设置:

  • 我的类中的一个字段:private CancellationTokenSource _cancellationTokenSource;
  • 每次我创建使用特定取消 token 的 TPL 任务时,都会启动此 CancellationTokeSource

实际的 TPL 任务如下所示:

var dataRetrievalTask = new Task<List<myType>>(() =>
            {
                // retrieve data and do something
                foreach (var a in retrievalMethod())
                {
                    if (_cancellationTokenSource.Token.IsCancellationRequested)
                        _cancellationTokenSource.Token.ThrowIfCancellationRequested();

                        // do something if not cancelled
                    }
                }

                return filledListOfMyType;

            }, _cancellationTokenSource.Token);

            // define what shall happen if data retrievel finished without any problems
            var writingLoadedDataToGridTask = dataRetrievalTask.ContinueWith(task =>
            {
              // do something in case we ran to completion without error
            }, _cancellationTokenSource.Token, TaskContinuationOptions.OnlyOnRanToCompletion, currentScheduler);

            // what to do in case cancellation was performed
            var loadingDataCancelledTask = dataRetrievalTask.ContinueWith(task =>
                              {
                                someLabel.Text = "Data retrieval canceled.";
                              },_cancellationTokenSource.Token, TaskContinuationOptions.OnlyOnCanceled, currentScheduler);

            // what to do in case an exception / error occured
            var loadingDataFaulted = dataRetrievalTask.ContinueWith(task =>
                {
                    someLabel.Text = string.Format("Data retrieval ended with an Error.");
                }, _cancellationTokenSource.Token, TaskContinuationOptions.OnlyOnFaulted, currentScheduler);

            // when any of the continuation tasks ran through, reset ui controls / buttons etc
            Task.Factory.ContinueWhenAny(new[] { writingLoadedDataToGridTask, loadingDataCancelledTask, loadingDataFaulted }, task =>
            {
              // reset controls and all that
            }, _cancellationTokenSource.Token, TaskContinuationOptions.None, currentScheduler);


            dataRetrievalTask.Start();

现在我的问题是,当在某个地方(在取消按钮的 .Click 事件处理程序中)调用 _cancellationTokenSource.Cancel() 方法时,不会调用特定的 loadingDataCancelledTask 的主体/方法。

我在这里做错了什么?我正在使用并移交相同的 _cancellationTokenSource.Token 实例...以及其他所有内容(“writingLoadedDataToGridTask”和“loadingDataFaulted”任务以及以下“Task.Factory.ContinueWhenAny(new [] {writingLoadedDataToGridTask,loadingDataCancelledTask,loadingDataFaulted },任务) => ...' block )确实有效。只有取消不起作用。有人看到/知道为什么吗?

最佳答案

您的取消延续正在被取消,因为它使用相同的取消 token 。

如果你仔细想想,这是完全有道理的:当你说“我想取消所有处理”时,你实际上得到了你所要求的。所有处理都会停止,包括更新 UI。

解决方案是不要将取消 token 用于取消、错误和 ContinueWhenAny 延续。这样这些延续就会始终运行。

关于.net - TPL 取消延续从未调用已取消的任务,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10563214/

相关文章:

c# - EventSource 事件 ID 和 TPL

c# - 尝试保存图像时出现一般 GDI+ 错误(在 64 位 Windows 7 上)

c# - MailKit:由于数据包格式意外,握手失败

.net - UWP中通过XAML触发设置ListView选中项

c# - 运行超过 2 个线程时 FtpWebRequest 超时

java - HashTable 中的 ArrayList 是线程安全的

c# - 打包vs2005项目

Java:生产者-消费者两个线程停止工作,卡住

c# - 请求取消 token 的任务事件或操作

c# - 任务和线程有什么区别?