2015-04-17 61 views
-1

我正在努力解決這個問題。在parallel.foreach中使用局部變量

該代碼應該從文件對話框導入圖像。並且每個圖像都應該被處理併發送給正確的類。 處理器是一個檢測形狀的類,所以基本上我發送每個圖像並檢測其中的形狀(在類處理器內過濾到特定標準)

newList將獲取圖像中所有形狀的中心。

我對並行性知之甚少,我似乎無法想象如何解決這個問題。請記住,我不需要將任何內容從一個迭代傳遞到另一個迭代。我只是希望每次處理和更正圖像,並將整個操作分爲線程。

我的每一次迭代都是獨立的,我不需要從一次迭代中返回任何東西。

目前的問題是,從正確的類返回的結果有時是不正確的。我想這是因爲處理器和newList也必須是本地的?如果是,我該如何解決這個問題?如果不是我哪裏出錯了?

而且要記住,使用普通的foreach工作得很好

這裏是我的代碼:

Parallel.ForEach(ofd.FileNames, 
     (file) => 
     { 
      Image exam = Image.FromFile(file); 
      var cvImage = new Image<Bgr, byte>((Bitmap)exam); 
      processor = processorMain; 
      processor.ProcessImage(cvImage); 
      List<Point> newList = new List<Point>(); 
      newList = processor.getList(); 
      correct.correct(cvImage, answerKey, nOptions); 
     }); 
+3

您是否注意到您完全沒有描述您的問題? :) – Rytmis

+0

問題是,這個Parallel.Foreach不起作用,我已經解釋了原因。我的每一次迭代都是獨立的,我不需要從一個迭代到另一個迭代。 – user3473655

+2

'Parallel.Foreach不起作用'我不知道這意味着什麼。 「我已經解釋了原因,你說過它應該做什麼。你沒有描述你看到的是什麼樣的行爲與你的期望。 – Jonesopolis

回答

2

實際問題/問題的評論指出:

我每一次迭代都是獨立的,我不需要從一次迭代中返回任何東西。

在這種情況下,你不希望你的Image是線程本地的,你只需要它們在本地。因此,解決辦法是簡化:

Parallel.ForEach(ofd.FileNames, 
    (file) => 
    { 
     var cvImage = new Image<Bgr, byte>((Bitmap)exam); 
     processor = processorMain; 
     processor.ProcessImage(cvImage); 
     List<Point> newList = new List<Point>(); 
     newList = processor.getList(); 
     correct.correct(newList, cvImage, answerKey, nOptions); 
    }); 

但你的代碼是不是真的用file任何地方,所以這只是一個粗略的猜測。它現在還不正確。

而另一方面,processorMainanswerKeynOptions的使用是潛在的問題。


,還有一些人的意見後,你需要的是:

IList<Image> result = ofd.FileNames 
     .AsParallel() 
     .Select((file) => 
{ 
    Image exam = Image.FromFile(file); 
    ... 
    return exam; 
}).ToList(); 
+0

感謝您的回覆 這就是我使用該文件的地方。我從每個文件名創建一個圖像,然後處理該圖像,然後發送到正確的類 – user3473655

+0

但是,在代碼中沒有任何地方使用'file'。你還沒有走出困境。 –

+0

正如我所說,文件是用來創建一個圖像從它 因此,這個代碼中的cvImage聲明之前是缺少一行: Image exam = Image.FromFile(file);正如你所預料的,由於proeccor和newList仍然存在問題。它們應該是本地化的?如果是,如何? – user3473655

0

你的問題很可能在這行代碼:

 processor = processorMain; 
     processor.ProcessImage(cvImage); 
     List<Point> newList = processor.getList(); // don't make a new list and then just throw it away by overwriting it. 

看起來processor正在處理您的圖像並存儲一些結果,您稍後可以訪問processor.getList()。但是如果多個線程並行運行,第二個線程可能在第一個線程調用它之後但在第一個線程到達processor.getList()之前調用ProcessImage。這意味着第一個線程將從第二個線程獲取列表結果。

最簡單的解決辦法是在每次迭代中創建一個處理器:

 processor = new MyProcessorType(); 
     processor.ProcessImage(cvImage); 
     List<Point> newList = new List<Point>(); 
     newList = processor.getList(); 

這是依賴於假設處理器不依賴於任何靜態數據。

另一種選擇是修改處理器,以便點列表存儲在線程本地存儲中。

+0

感謝您的答覆。我明白你的意思,這是真的。但讓我告訴你爲什麼我總是使用processor = processorMain。 processorMain包含圖像處理的預定義設置,如果我寫入processor = new MyProcessorType(),則會丟失這些設置。所以processor = processorMain基本上是重置了我在每次圖像處理中需要的processorMain中的值。再次感謝 – user3473655

+0

是的,你有每個線程共享相同的狀態。該狀態包含該配置。問題是,每個線程調用處理狀態的ProcessImage,然後他們調用getList來讀取狀態。您需要複製每個線程需要的配置,併爲它們提供自己的工作空間。如果他們都在同一時間使用同一個對象,那麼您將遇到這些問題。 – Erik

+0

謝謝,我通過在newList上應用鎖並解決了問題 – user3473655