相当于并行中的 do() while{}

发布于 2024-12-04 02:33:38 字数 676 浏览 2 评论 0原文

如何在下面的 Update() 方法中创建与 do-while 或类似的并行等效项?

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

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

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

旧竹 2024-12-11 02:33:38

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

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

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);
    }
});
很快妥协 2024-12-11 02:33:38

for/foreach 通常用于对多个项目执行任务。

while-do/do-while 用于

:对多个项目执行任务
尚未枚举的(例如树)。
- 在这种情况下,您可以定义 BFS 或 DFS 枚举器并在 foreach 中使用。

b.对单个项目执行迭代工作
- 迭代工作不适合并行

不要尝试将代码从串行重构为并行。相反,请考虑您的任务是什么以及如何最好地并行完成它。 (重构算法,而不是代码。)

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.)

像极了他 2024-12-11 02:33:38
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; 
}
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; 
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文