1

タイプ myObjs のオブジェクトのリストがあるとしますList<Foo>

私はポリーポリシーを持っています:

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

メソッドを並行して実行したいのですが、失敗してもそれぞれを再試行し続けます。

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

これは並行して呼び出され、各オブジェクトを再試行しますか? myObjs[5].do() が失敗した場合、他のオブジェクトは 1 回だけ実行され、それだけが再試行されるのでしょうか?

また、例に示すように、Execute(Action) メソッドの代わりに Func を受け入れる ExecuteAsync() メソッドを使用することになっていますか? 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 エラー 2 3 4 5

あと数回 2 を再試行すると思っていましたが、そうではありません。理由はありますか?

4

1 に答える 1

2

タスクを所有するものは何でも、何らかの方法でそれらを待たなければなりません。そうしないと、例外は無視され、タスクが実際に完了する前にコードが終了します。そうです、おそらくpolicy.ExecuteAsync()代わりに使用する必要があります。次のようになります。

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

// sometime later
await Task.WhenAll(tasks);
于 2016-10-24T16:21:59.133 に答える