Parallel ForEach或For循环中的返回值和关键字

问题描述:

从Parallel ForEach或For循环返回值的正确方法是什么?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; 
} 

最后什么回报关键字的并行For或ForEach循环内的行为?

IE:它是否立即终止所有线程?它会导致你可能不期望的任何文物?

希望我所问的是有道理的。 PS:更具体一点。看看第一个例子是我对String线程安全的修改,并且包含我期望的值,因为返回语句?在第二个例子中,我修改了List Collection线程安全吗?我期望添加的所有值都会被添加吗?

我在这里使用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() 

肯定会是更好的选择?

+0

我只是在玩这个概念。我认为它可能不会。 – 2011-03-29 14:06:15

+0

只是我吗?上面的代码会引发以下错误:Win32Exception被用户代码无法处理。访问被拒绝 - 我猜它与比较句柄有关? – 2011-03-29 14:44:08

+0

不是在我的情况,我有我自己的自定义窗口类。它实现了过程对象不提供的功能。我只是想避免另一个API调用并且玩弄这个概念。看起来它在标准循环中也不起作用。哎呦! – 2011-03-29 15:02:42

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

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

上述所有答案+的:

如果你想发出信号回路应停止,你应该使用ParallelLoopState(你可以通过Action<T, ParallelLoopState>代替Action<T>代表访问该对象。状态对象具有类似于.Stop().Break()的方法,这将表示您要停止执行循环(以及其他一些有用的属性,请自行尝试)。