[英]How to cancel the whole tpl dataFlow on first exception?
考虑以下示例:
ActionBlock<TimeSpan> ab = new ActionBlock<TimeSpan>(async _ =>
{
await Task.Delay(_);
throw new Exception();
}, new ExecutionDataflowBlockOptions() { MaxDegreeOfParallelism = Int32.MaxValue });
ab.Post(TimeSpan.FromSeconds(10d));
ab.Post(TimeSpan.FromDays(1d));
await ab.Completion;
不出所料,我在输出窗口中看到10秒后将引发异常,但这不会导致dataFlow完成(等待ab之后的断点。完成不会在1天前命中)。
就我而言,如果单个计算步骤中有异常,我想取消整个dataFlow。
我看不到如何使用tpl dataflow做到这一点...有什么建议吗?
谢谢...
[edit]如Ofir所述,我可以这样做:
ActionBlock<TimeSpan> ab = new ActionBlock<TimeSpan>(async _ =>
{
try
{
await Task.Delay(_);
throw new Exception();// Or any other Task thay may throw an exception.
}
catch(Exception)
{
cancelTokenSource.Cancel();
throw;
}
}, new ExecutionDataflowBlockOptions() {CancellationToken=cancelTokenSource.Token, MaxDegreeOfParallelism = Int32.MaxValue });
ab.Post(TimeSpan.FromSeconds(10d));
ab.Post(TimeSpan.FromDays(1d));
await ab.Completion;
但这正是我要避免的事情:一次又一次地键入相同的try {} catch……或更糟糕的是:忘记了...;)
我接下来要做的是编写一个替代ActionBlock的构造函数来处理该问题(这将需要一个额外的CancellationTokenSource参数)...我很惊讶这不是直接与数据流一起出现的吗?确实如此吗?
[最终编辑]似乎答案是tpd dataFlow中没有这样的东西 ,而将CancellationTokenSource作为参数的ActionBlock "extension constructor" (in fact a static method)
可能是一种解决方法...
您抛出的Exception
将使ActionBlock
进入故障状态,并将所有要缓冲的消息丢弃,并且不接受更多消息。
对于CancelationToken
(可以在ExecutionDataflowBlockOptions
提供)也是如此。
当前处理的消息完成后,您将在await ab.Completion
上收到AggregateException
。
与Task
,您必须自己照顾已经执行的消息的中止。
为了演示,在您提供的示例中,可以这样实现:
var cancellationTokenSource = new CancellationTokenSource();
var ab = new ActionBlock<TimeSpan>(async _ =>
{
// await with cancellation token
await Task.Delay(_, cancellationTokenSource.Token);
cancellationTokenSource.Cancel();
}, new ExecutionDataflowBlockOptions {CancellationToken = cancellationTokenSource.Token, MaxDegreeOfParallelism = int.MaxValue});
ab.Post(TimeSpan.FromSeconds(10));
ab.Post(TimeSpan.FromSeconds(20));
Thread.Sleep(15000);
cancellationTokenSource.Cancel();
ab.Post(TimeSpan.FromSeconds(100));
try { await ab.Completion; }
catch(TaskCancelationException ex)
{ }
在上述情况下,我们将发布2条消息,这些消息将立即运行。
10秒钟后,第一条消息将导致Cancel
( cancellationTokenSource
并导致另一条消息(那延迟20秒)立即完成,并将ActionBlock
置于canceled状态。 我们尝试发布的下一条消息不会被接受,也不会执行。
15秒后,我们将在等待completion
收到TaskCancelationException
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.