并行ForEach或For循环内的返回值和关键字

时间:2011-03-29 14:01:35

标签: c# multithreading thread-safety parallel-processing task-parallel-library

从Parallel ForEach或For循环返回值的正确方法是什么?

例如以下代码是否正确/ threadsafe?

{
    Process[] processes = Process.GetProcesses();
    String ProcessName = String.Empty;
    Parallel.ForEach(processes, curItem => {
        if (curItem.Handle == this._handle) {
            ProcessName = curItem.ProcessName;
            return;
        }
    });
    return ProcessName;
}

还是这个?

{
    Process[] processes = Process.GetProcesses();
    List<String> ProcessNames = new List<String>();
    Parallel.ForEach(processes, curItem => {
            ProcessNames.Add(processes.ProcessName);
        }
    });
    return ProcessNames;
}

最后,Parallel For或ForEach循环中的return关键字的行为是什么?

IE:它会立即终止所有线程吗?它会导致你可能没想到的任何文物吗?

希望我所要求的是有道理的。

PS:更具体一点。看第一个例子是我对String threadsafe的修改,并且由于return语句而包含我期望的值?在第二个例子中是我对List Collection线程安全的修改?我期望的所有价值都会被添加吗?

4 个答案:

答案 0 :(得分:9)

我在这里使用PLINQ:

return Process
    .GetProcesses()
    .AsParallel()
    .SingleOrDefault(p => p.Handle == this._handle);

我想知道你在这里处理的数据量是否值得并行......

要更直接地回答您的问题,为了处理从并行循环中提前退出,您应该查看将ParallelLoopState交给执行委托的重载。这可用于控制早期循环终止。

编辑:

您看到的错误是因为您的进程没有足够的权限来访问您检查的进程的句柄。处理这种情况的蛮力方式如下:

Process
.GetProcesses()
//.AsParallel()
.Where(p=>{try{var h=p.Handle;}catch{return false;}return true;})
.SingleOrDefault(p => p.Handle == this._handle)

当然,假设this._handle引用当前正在执行的进程的句柄:

Process.GetCurrentProcess()

肯定会更合适吗?

答案 1 :(得分:6)

并行foreach循环中的

return与普通循环中的continue基本相同,因为return位于为每个项执行的委托内。这意味着,它不会终止任何线程,特别是不会终止并行foreach循环的执行。

答案 2 :(得分:6)

以上所有答案+:

如果你想要发出循环应该停止的信号,你应该使用ParallelLoopState(你可以通过传递Action<T, ParallelLoopState>而不是Action<T>委托来访问这个对象。状态对象有{{1}之类的方法1}}或.Stop()表示您想要停止执行循环(以及其他一些有用的属性,请自行尝试)。

答案 3 :(得分:5)

两者都不正确。你正在寻找一个价值? Parallel.ForEach在这里是错误的解决方案。您要找的是reduction,而ForEach执行mapping。可以使用PLINQ执行并行缩减。