TPL取消继续从未在已取消的任务上调用 [英] TPL cancellation continuation never called on cancelled Task

查看:34
本文介绍了TPL取消继续从未在已取消的任务上调用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的代码中利用TPL进行了以下设置:

I have the following setup in my code that utilizes the TPL:

  • 我班上的一个字段:私人CancellationTokenSource _cancellationTokenSource;
  • 每次我创建一个使用该特定Cancellationtoken的TPL任务时,此CancellationTokeSource都会失效

实际的TPL任务如下:

The actualy TPL tasks look like this:

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()方法时,没有调用特定的loadDataCancelledTask的主体/方法.

Now my problem is that when the _cancellationTokenSource.Cancel() method is called somewhere (in a Cancel-button's .Click event handler) that particular loadingDataCancelledTask's body/method isn't called.

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

What am I doing wrong here? I am using and handing over the same _cancellationTokenSource.Token instance... and everything else (the 'writingLoadedDataToGridTask' and 'loadingDataFaulted' tasks & the following 'Task.Factory.ContinueWhenAny(new[] { writingLoadedDataToGridTask, loadingDataCancelledTask, loadingDataFaulted }, task => ...' block) do actually work. Only cancellation does not. Does anyone see/know why?

推荐答案

您的取消继续被取消,因为它使用相同的取消令牌.

Your cancellation continuation is being cancelled because it uses the same cancellation token.

如果您考虑一下,这是完全有道理的:当您说我想取消所有处理"时,您实际上会得到您想要的.停止所有处理,包括更新UI.

If you think about it it makes total sense: When you say "I want to cancel all processing" you actually get what you ask for. All processing stops, including updating the UI.

解决方案是不对取消,错误和 ContinueWhenAny 延续使用取消令牌.这样,这些连续性就会一直运行.

The solution is to not use the cancellation token for the cancel, error and ContinueWhenAny continuations. That way these continuations always run.

这篇关于TPL取消继续从未在已取消的任务上调用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆