c# - Interlocked.Decrement(i) 适合 Parallel.ForEach() 吗?

标签 c# multithreading parallel-processing

过去我这样做过:

List<Item> _Items = GetItems();
int _CountDown = _Items.Count;
using (BackgroundWorker _Worker = new BackgroundWorker())
{
    _Worker.DoWork += (s, arg) =>
    {
        DoSomething(_Items[_CountDown]);
    };
    _Worker.RunWorkerCompleted += (s, arg) =>
    {
        if (System.Threading.Interlocked.Decrement(ref _CountDown) == 0)
            RaiseAllDoneEvent();
        else
            _Worker.RunWorkerAsync();
    };
    _Worker.RunWorkerAsync();
}

使用并行,我会做这样的事情:

List<Item> _Items = GetItems();
int _CountDown = _Items.Count;
System.Threading.Tasks.Parallel.ForEach(_Items, (i) =>
{
    DoSomething(i);
    if (System.Threading.Interlocked.Decrement(ref _CountDown) == 0)
        RaiseAllDoneEvent();
});

我真正的问题是:Interlocked.Decrement() 这里正确吗?

最佳答案

Parallel.ForEach 将阻塞,直到处理完所有项目 - 这里正确的做法似乎是在调用 Parallel.ForEach 之后立即从调用者调用 RaiseAllDoneEvent():

List<Item> _Items = GetItems();
System.Threading.Tasks.Parallel.ForEach(_Items, (i) =>
{
    DoSomething(i);
});
RaiseAllDoneEvent();

换句话说,根本不需要倒计时(或跟踪有多少项目需要处理)。如果你想让并行操作不被阻塞,你可以把它变成一堆任务:

List<Item> _Items = GetItems();
Task.Factory.StartNew(()=> { 
        Task.WaitAll(
            _Items.Select(i => Task.Factory.StartNew(() => DoSomething(i))).ToArray()
        ); 
    }).ContinueWith(t => RaiseAllDoneEvent());

在这种情况下,您将启动一个外部任务来旋转,然后等待一堆任务(每个项目一个),最后引发所有完成事件。这些都不会阻止原始调用者。

关于c# - Interlocked.Decrement(i) 适合 Parallel.ForEach() 吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7276603/

相关文章:

c# - C#中多个线程调用同一个方法

windows - 在 r 中并行使用 wordnet(与 windows 7)

performance - 多线程时现代操作系统上的目录漫游器变慢?

c++ - 是否可以在 C++ 中检查 (this == NULL) 以终止分离线程的执行?

java - 在 Java 中使用线程时维护 FIFO

arrays - Julia:在表达式中使用分布式数组

c# - 在循环数据时创建列表列?

c# - viewbag 没有将 `id` 保存到后期操作中

c# - Asp.Net Core 2.0 中 Httpcontext.Current.Request.Files 的替代方案是什么?

c# - 如何在 mshtml 和 c# 中启用多级撤消/重做