7

從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線程安全嗎?我期望添加的所有值都會被添加嗎?

回答

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

肯定會是更好的選擇?

+0

我只是在玩這個概念。我認爲它可能不會。 – 2011-03-29 14:06:15

+0

只是我嗎?上面的代碼會引發以下錯誤:Win32Exception被用戶代碼無法處理。訪問被拒絕 - 我猜它與比較句柄有關? – 2011-03-29 14:44:08

+0

不是在我的情況,我有我自己的自定義窗口類。它實現了過程對象不提供的功能。我只是想避免另一個API調用並且玩弄這個概念。看起來它在標準循環中也不起作用。哎呦! – 2011-03-29 15:02:42

6

return在並行foreach循環內基本上與正常循環中的continue相同,因爲return位於爲每個項目執行的委託內部。這意味着它不會終止任何線程,特別是不會終止並行foreach循環的執行。

5

兩者都不正確。你正在尋找一個價值? Parallel.ForEach這裏是錯誤的解決方案。你在找什麼是reduction,而ForEach執行mapping。可以使用PLINQ執行並行壓縮。

6

上述所有答案+的:

如果你想發出信號迴路應停止,你應該使用ParallelLoopState(你可以通過Action<T, ParallelLoopState>代替Action<T>代表訪問該對象。狀態對象具有類似於.Stop().Break()的方法,這將表示您要停止執行循環(以及其他一些有用的屬性,請自行嘗試)。