簡體   English   中英

識別TPL數據流中的同時任務

[英]identifiing the simultaneous tasks in a TPL dataflow

我在TPL數據流塊中有1000個元素,每個元素都會調用外部Web服務。

Web服務最多支持10個同時呼叫,這可以通過以下方式輕松實現:

new ExecutionDataflowBlockOptions
{
    MaxDegreeOfParallelism = 10
    ...
}

Web服務要求每個調用都有一個唯一的id,它將其與其他同時調用區分開來。 理論上這應該是一個guid,但實際上第11個GUID將失敗 - 因為服務器上的限制機制很難識別第一個調用已完成。

供應商建議我們回收guids,保持10個正在使用。

我打算有一個GUID數組,每個任務都會使用(Interlocked.Increment(ref COUNTER)%10)作為數組索引

編輯:我剛剛意識到這不起作用! 它假設任務將按順序完成,我們可能無法將其作為ID隊列實現,其中每個任務借用並返回一個,但問題仍然存在,是否有一個更容易的,預備好的線程安全的方法來做到這一點?

(永遠不會有足夠的呼叫讓COUNTER溢出)

但是我很多次對C#(我是.net的新手)感到驚訝,我正在實現已經存在的東西。

是否有更好的線程安全方式讓每個任務從一個id池中回收?

創建資源池的確切情況是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);
        }
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM