开发者

Equivalent of do() while{} in Parallel

开发者 https://www.devze.com 2023-04-04 06:53 出处:网络
How can I create the parallel equivalent of a do-while or similar in the Update() method below? Another thread in the app writes to TestBuffer at random. TestBuffer.RemoveItemAndDoSomethingWithIt();

How can I create the parallel equivalent of a do-while or similar in the Update() method below?

Another thread in the app writes to TestBuffer at random. TestBuffer.RemoveItemAndDoSomethingWithIt(); should run 开发者_C百科until the TestBuffer is empty. Currently Update() only runs with the items that were in the collection when it was was enumerated, which makes sense.

internal class UnOrderedBuffer<T> where T : class
{
    ConcurrentBag<T> GenericBag = new ConcurrentBag<T>();
}

internal class Tester
{
    private UnOrderedBuffer<Data> TestBuffer;

    public void Update()
    {
        Parallel.ForEach(TestBuffer, Item =>
        {
            TestBuffer.RemoveItemAndDoSomethingWithIt();
        });
    }
}


You could force a single execution by 'prepending' a null/default value:

static IEnumerable<T> YieldOneDefault<T>(this IEnumerable<T> values)
{
    yield return default(T);
    foreach(var item in values)
        yield return item;
}

And then use it as follows:

Parallel.ForEach(TestBuffer.YieldOneDefault(), Item =>  
{  
    if(Item != null)
      TestBuffer.RemoveItemAndDoSomethingWithIt();
    else
      DoSomethingDuringTheFirstPass();
});  

Although I suspect you might be looking for the following extension methods:

public static IEnumerable<IEnumerable<T>> GetParrallelConsumingEnumerable<T>(this IProducerConsumerCollection<T> collection)
{
    T item;
    while (collection.TryTake(out item))
    {
        yield return GetParrallelConsumingEnumerableInner(collection, item);
    }
}

private static IEnumerable<T> GetParrallelConsumingEnumerableInner<T>(IProducerConsumerCollection<T> collection, T item)
{
    yield return item;
    while (collection.TryTake(out item))
    {
        yield return item;
    }
}

Which will let get you this result (which I think is what you are after):

Parallel.ForEach(TestBuffer.GetParrallelConsumingEnumerable(), Items =>       
{
    foreach(var item in Items)
    {
       DoSomethingWithItem(item);
    }
});


for/foreach are usually used for performing a task on multiple items.

while-do/do-while are for:

a. Performing a task on multiple items that have not yet been enumerated (e.g. a tree).
- In this case you can define a BFS or DFS enumerator and use in a foreach.

b. Performing iterative work on a single item
- Iterative work is not suitable for parallelism

Do not attempt to refactor code from serial to parallel. Instead, consider what your assignment is and how it is best done in parallel. (Refactor algorithm, not code.)


public static void While( 
    ParallelOptions parallelOptions, Func<bool> condition, 
    Action<ParallelLoopState> body) 
{ 
    Parallel.ForEach(Infinite(), parallelOptions, (ignored, loopState) => 
    { 
        if (condition()) body(loopState); 
        else loopState.Stop(); 
    }); 
}

private static IEnumerable<bool> Infinite() 
{ 
    while (true) yield return true; 
}
0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号