并行中等于do()而{}

时间:2011-09-13 10:08:34

标签: c# parallel-processing plinq

如何在下面的Update()方法中获得与while或类似的并行等效的代码。

应用程序中的另一个线程随机写入Testbuffer。 TestBuffer.RemoveItemAndDoSomethingWithIt();应运行直到Testbuffer为空。目前Update()仅运行枚举时集合所在的项目。这是有道理的......

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


namespace Test
{
  internal class Tester
  {
    private UnOrderedBuffer<Data> TestBuffer;

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

3 个答案:

答案 0 :(得分:3)

您可以通过“预先设置”空/默认值来强制执行一次:

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

然后按如下方式使用它:

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

虽然我怀疑您可能正在寻找以下扩展方法:

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;
    }
}

哪个会让你得到这个结果(我认为你就是这样):

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

答案 1 :(得分:3)

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 you assignment is and how it is best done in parallel.
(Refactor algorithm, not code.)

答案 2 :(得分:0)

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; 
}