我使用的动作块看起来像这样:
ActionBlock<Tuple<string,byte[],string>> ab =
new ActionBlock<Tuple<string,string,string>>(item => {
service.DoSomeAction(item.Item1, item.Item2, item.Item3);
},
new ExecutionDataflowBlockOptions {
MaxDegreeOfParallelism = 2
});
foreach(var item in Items) {
ab.Post(new Tuple<string,string,string>(item.a, item.b, item.c));
}
ab.Complete();
ab.Completion.Wait();
我的问题是service.DoSomeAction()
可能由于网络负载而失败,我想知道ActionBlock是否有重新启动任务的机制。
我当然可以在该调用周围添加一个try / catch块,并在重新抛出异常之前让catch块等待/重试几次。我要找的是用相同的参数调用ab.Post()
。我的问题是我已经打电话给ab.Complete()
了。是否可以在不调用ab.Complete()
的情况下等待ActionBlock。是否有更好的工具可用于工作?
答案 0 :(得分:5)
是否可以在不调用
ab.Complete()
的情况下等待ActionBlock。
是的,请不要拨打电话直接转到ab.Completion.Wait();
(旁注:如果可能,您应该使用await ab.Completion;
),但< / strong>其他人需要拨打ab.Complete()
,否则会因为ab.Completion
永远无法完成而无法等待。
但是为什么你不想使用&#34;尝试/捕获/重试&#34;行动中的逻辑?国际海事组织这将是更好的方法
例如。使用TransientFaultHandling.Core
你可以做类似的事情:
var retry = new RetryPolicy(ErrorDetectionStrategy.On<Exception>(), // see http://pastebin.com/6tmQbkj4
3, TimeSpan.FromMilliseconds(250));
ActionBlock<Tuple<string,byte[],string>> ab =
new ActionBlock<Tuple<string,string,string>>(item =>
retry.ExecuteAction(() => service.Action(item.Item1, item.Item2, item.Item3)),
new ExecutionDataflowBlockOptions {
MaxDegreeOfParallelism = 2
});
答案 1 :(得分:0)
我对ActionBlock
了解不多,您是否只能使用Parallel
课程?
这样的事情:
Parallel.ForEach(Items, item =>
{
bool succeeded = false;
while(!succeeded)
{
try
{
service.DoSomeAction(item.Item1, item.Item2, item.Item3);
succeeded = true;
}
catch(MyException) //the expected Exception, let others get thrown
{
}
}
});