2016-02-04 70 views
1

嗨,我在下面的代碼工作:C#並行共享內部變量

  Parallel.For(1, residRanges.Count, i => 
      { 
       int count = 0; 
       List<double> colAList = new List<double>(); 
       List<double> colBList = new List<double>(); 
       for (int x = 0; x < residErrorData.Count; x++) 
       { 
        foreach (pricateConnection in residErrorData[x].connList) 
        { 
         if (residRanges[i].connection == nc.connection) 
         { 
          colAList.Add(residErrorData[x].residualError); 
          colBList.Add(nc.freq); 
          count = count + 1; 
         } 
        } 
       } 
       colA = new double[count]; 
       colB = new double[count]; 
       for (int j = 0; j < count; j++) 
       { 
        colA[j] = colAList[j]; 
        colB[j] = colBList[j]; 
       } 

       residRangeError tempresid = residRanges[i]; 
       tempresid = fitResid(tempresid, colA, colB);      

       residRanges[i] = tempresid; 
       residRanges[i].n = count;       
       } 
      }); 

如果我不使用並行類自己的價值觀似乎然而,當我使用並行類由於某種原因,要準確它會混合colA和colB的值。它在線程之間混合它們。我對並行處理相當陌生,但我一直在環顧四周,似乎無法找到任何解決方案。有誰知道爲什麼程序似乎在線程之間共享變量?

我知道代碼並不理想我一直在嘗試不同的事情來弄清楚發生了什麼問題。我並沒有試圖在此刻進行優化,理解爲什麼不同循環中的變量不會分開。

residRanges []是類項目的列表。 for循環使用它似乎得到正確的值,他們剛剛開始混淆了哪些值在Parallel.For中運行的位置。

感謝您的幫助!我真的可以使用它!

+0

什麼其他變量包含在閉包中?您可能會遇到線程不安全的問題。我認爲問題在於你將'colA'和'colB'從lambda中提取出來。將它們移到本地範圍。 – Dai

+0

@Dai總是右''colA'和'colB'是並行計算內部的本地,試着改變'colA = new double [count];'var var colA = new double [count];''colB' – csharpfolk

+0

非常感謝你!這非常有道理,我忘了我已經在循環之外創建了這些變量。非常感謝! – HipposWild

回答

1

(轉貼作爲甜,甜人緣答案)

您的代碼看起來好像colAcolB的拉姆達的範圍,這意味着變量引用可以指不同的陣列之外聲明的對象爲不同的線程同時運行(例如線程0會改變colA而線程1是for j < count循環內

移動聲明colAcolB到拉姆達內:

... 
Double[] colA = new double[count]; 
Double[] colB = new double[count]; 
for (int j = 0; j < count; j++) 
... 

但是我看到你實際上並沒有做任何有用與colAcolB不是利用他們作爲你fitResid函數值保持其他的,你可以簡化這個:

  1. 更改fitResid函數簽名接受IList<Double>代替Double[]
  2. 更改fitResid函數調用通過消除不必要的複製和內存分配在colAList,並分別colBList通過,這將加快您的代碼:

    ...    
    residRanges[i] = fitResid(residRanges[i], colAList, colBList); 
    residRanges[i].n = count;   
    ...