在ActionBlock中重新提交失败的任务

时间:2015-01-21 15:31:53

标签: c# .net task-parallel-library

我使用的动作块看起来像这样:

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。是否有更好的工具可用于工作?

2 个答案:

答案 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
        {
        }
    }
});