我正在使用
据我理解,第一种选项会取消整个块,从而关闭整个流水线。我的问题是:如果有任何资源(例如打开的StreamReaders等),它是否也会取消内部操作并处理所有资源,还是最好选择第二个选项,然后我自己可以确保取消和清理所有内容,然后我可以使用某些手段(铁路编程)来将抛出的
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 向下传递管道,并在我想要的地方对其进行处理?
DoSometheningWithData()
也应该检查_downloadCts
,可能使用_downloadCts.ThrowIfCancellationRequested()
。如果您正在处理可处置资源,请将它们放在using()
块中以确保它们被丢弃。 - user585968ISourceBlock
结束(无论出于什么原因),它就可以通知所有链接的ITargetBlock
。为了使其像这样工作,您必须在Link
调用期间指定以下内容:new DataflowLinkOptions { PropagateCompletion = true }
我的建议是考虑取消 生产者 部分,而不是 消费者。 - Peter Csala