2017-06-26 2 views
1

TPLデータフローブロックに1000個の要素があります。 各要素は外部Webサービスを呼び出します。は、TPLデータフローの同時タスクを識別します

new ExecutionDataflowBlockOptions 
{ 
    MaxDegreeOfParallelism = 10 
    ... 
} 

Webサービスは、他の同時コールからそれをdistinguises渡された一意のIDを持つように各呼び出しを必要とします。

Webサービスを簡単に使用して達成された10回の同時コール、 の最大をサポートしています。 これはguidである必要がありますが、実際には11番目のGUIDは失敗します。サーバーのスロットルメカニズムが最初の呼び出しが完了したことを認識するのが遅いためです。

ベンダーは、guidsをリサイクルし、10をアクティブに保つことを提案しています。

私は、各タスクは、配列インデックス

EDITとして(Interlocked.Increment(REF COUNTER)%10)を使用します、GUIDの配列を持っているつもり: 私は、これは動作しません実現! タスクが完了しないと仮定します これは、各タスクが借りて1つを返すIDのキューとして実装できますが、問題はまだありません。これは、より簡単で事前にスレッドで安全な方法ですこの?

(オーバーフローのCOUNTERのための十分な呼び出しがあることは決してありません)しかし、私はすでに存在している何かを実装していますC#の(私はネットに新たなんだ)によって回数を驚かせてきました。

各タスクがIDのプールからリサイクルするのに適したスレッドセーフな方法はありますか?

答えて

3

リソースプールの作成は、正確な状況であるSystem.Collections.ConcurrentBag<T>が役に立ちます。コードを簡単にするためにBlockingCollection<T>にまとめてください。

class Example 
{ 
    private readonly BlockingCollection<Guid> _guidPool; 
    private readonly TransformBlock<Foo, Bar> _transform;  

    public Example(int concurrentLimit) 
    { 
     _guidPool = new BlockingCollection<Guid>(new ConcurrentBag<Guid>(), concurrentLimit) 
     for(int i = 0: i < concurrentLimit; i++) 
     { 
      _guidPool.Add(Guid.NewGuid()); 
     } 

     _transform = new TransformBlock<Foo, Bar>(() => SomeAction, 
                new ExecutionDataflowBlockOptions 
                { 
                MaxDegreeOfParallelism = concurrentLimit 
                //... 
                }); 
     //... 
    } 

    private async Task<Bar> SomeAction(Foo foo) 
    { 
     var id= _guidPool.Take(); 
     try 
     { 
      //... 
     } 
     finally 
     { 
      _guidPool.Add(id); 
     } 
    } 
} 
関連する問題