【发布时间】:2020-05-29 07:19:00
【问题描述】:
我正在使用TPL 块来执行可能被用户取消的操作:
我提出了两个选项,首先我取消整个块但不取消块内的操作,如下所示:
_downloadCts = new CancellationTokenSource();
var processBlockV1 = new TransformBlock<int, List<int>>(construct =>
{
List<int> properties = GetPropertiesMethod(construct );
var entities = properties
.AsParallel()
.Select(DoSometheningWithData)
.ToList();
return entities;
}, new ExecutionDataflowBlockOptions() { CancellationToken = _downloadCts.Token });
第二个我取消内部操作,但不是块本身:
var processBlockV2 = new TransformBlock<int, List<int>>(construct =>
{
List<int> properties = GetPropertiesMethod(construct);
var entities = properties
.AsParallel().WithCancellation(_downloadCts.Token)
.Select(DoSometheningWithData)
.ToList();
return entities;
});
据我了解,第一个选项将取消整个块,从而关闭整个管道。我的问题是它是否也会取消内部操作并处置所有资源(如果有的话(打开 StreamReaders 等)或者最好选择第二个选项,然后我自己可以确保所有内容都被取消和清理,然后我可以使用一些方法(铁路编程)将OperationCanceledException 浮出管道并在我想要的地方处理它?
【问题讨论】:
-
您应该将取消令牌传递给所有方法
-
"Cancel" 只是表示你请求一个愿望 让事情结束。除非有东西检查这个标志,否则它不会结束。这意味着
DoSometheningWithData()也应该与_downloadCts一起检查_downloadCts.ThrowIfCancellationRequested ()。如果您正在处理一次性资源,请将它们放在using()块中以确保它们被丢弃 -
TPL 的真正威力是从几个不同的构建块构建管道。因此,它的设计方式是,每当
ISourceBlock结束(无论出于何种原因),它都可以通知所有链接的ITargetBlocks。为了像这样工作,您必须在Link通话期间指定以下内容:new DataflowLinkOptions { PropagateCompletion = true }我的建议是考虑取消 producer 部分,而不是 consumer
标签: c# task-parallel-library tpl-dataflow cancellationtokensource