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

Max*_*ich 7 c# parallel-processing multithreading thread-safety 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;
}
Run Code Online (Sandbox Code Playgroud)

或这个?

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

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

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

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

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

spe*_*der 9

我在这里使用PLINQ:

return Process
    .GetProcesses()
    .AsParallel()
    .SingleOrDefault(p => p.Handle == this._handle);
Run Code Online (Sandbox Code Playgroud)

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

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

编辑:

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

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

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

Process.GetCurrentProcess()
Run Code Online (Sandbox Code Playgroud)

肯定会更合适吗?


Dan*_*rth 6

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


Mar*_*uła 6

以上所有答案+:

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


Kon*_*lph 5

两者都不正确.你正在寻找一个价值?Parallel.ForEach这是错误的解决方案.您正在寻找的是减少,同时ForEach执行映射.可以使用PLINQ执行并行缩减.