Equivalent of do() while{} in Parallel
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;
}
精彩评论