使用polly并行化任务

时间:2016-10-24 15:49:24

标签: c# async-await task-parallel-library polly

假设我有一个List<Foo>类型的对象myObjs列表。

我有一个polly政策:

var policy = Policy.Handle<Exception>().RetryForever();

我想在parralel中运行方法,但在失败时继续重试。

for (int i = 0; i < myObjs.Count; i++)
{
  var obj = myObjs[i];
  policy.Execute(() => Task.Factory.StartNew(() => obj.Do(), TaskCreationOptions.LongRunning));
}

是否会并行调用并重试每个obj?因此,如果myObjs [5] .do()失败,只会重试,而其他对象只执行一次?

另外,我是否应该使用ExecuteAsync()方法接受Func而不是Execute(Action),如示例所示? Do()只是一个同步方法,在一个单独的线程中启动。 实际代码如下所示,其中each()只是一个foreach包装器()

_consumers.ForEach(c => policy.Execute(() => Task.Factory.StartNew(() => c.Consume(startFromBeg), TaskCreationOptions.LongRunning)));

编辑:

我尝试了代码:

class Foo    
{
        private int _i;
        public Foo(int i)
        {
            _i = i;
        }
        public void Do()
        {
            //var rnd = new Random();
            if (_i==2)
            {
                Console.WriteLine("err"+_i);

                throw new Exception();
            }
            Console.WriteLine(_i);
        }
}
var policy = Policy.Handle<Exception>().Retry(3);
var foos=Enumerable.Range(0, 5).Select(x => new Foo(x)).ToList();
foos.ForEach(c => policy.Execute(() => Task.Factory.StartNew(() => c.Do(), TaskCreationOptions.LongRunning)));

但结果如下:

  

0 1 err2 3 4 5

我认为它会重试2次,但不会。知道为什么吗?

1 个答案:

答案 0 :(得分:1)

无论拥有什么任务,都必须以某种方式等待他们。否则,exceptions will be ignored和代码将在任务实际完成之前结束。所以是的,您应该使用policy.ExecuteAsync()代替。它看起来像这样:

var tasks = myObjs
    .Select(obj => Task.Factory.StartNew(() => obj.Do(), TaskCreationOptions.LongRunning))
    .ToList();

// sometime later
await Task.WhenAll(tasks);