我在使用TPL的代码中进行了以下设置:
实际的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();
现在我的问题是,在某处(在Cancel-button的.Click事件处理程序中)调用_cancellationTokenSource.Cancel()方法时,不会调用特定的loadingDataCancelledTask的body /方法。
我在这里做错了什么?我正在使用并移交相同的_cancellationTokenSource.Token实例......以及其他所有内容('writingLoadedDataToGridTask'和'loadingDataFaulted'任务以及以下'Task.Factory.ContinueWhenAny(new [] {writingLoadedDataToGridTask,loadingDataCancelledTask,loadingDataFaulted}, task =&gt; ...'block)确实有用。只有取消没有。有没有人看到/知道为什么?
答案 0 :(得分:8)
取消续订正在取消,因为它使用相同的取消令牌。
如果你仔细想想它是完全有道理的:当你说“我想取消所有处理”时,你实际上得到了你所要求的。所有处理都会停止,包括更新UI。
解决方案是不使用取消令牌来取消,错误和ContinueWhenAny
延续。这样,这些延续总是在运行。