1

我正在嘗試使用Parallel.ForEach生成唯一定時線程的Windows服務。問題在於,如果我將代碼單獨留在VS中幾個小時,或者如果我停止服務幾個小時並啓動任何備份 - 初始啓動代碼將執行兩次。這是服務的OnStart調用的靜態void的片段。僅當代碼尚未運行時,Parallel.ForEach纔會在啓動時執行兩次?

Parallel.ForEach(urls, url => 
        { 
         PageGrabber pagegrab = new PageGrabber(url); 
         if (url.Type.ToLower() == "http") 
         { 
          pagegrab.Elapsed += (obj, e) => 
           { 
            pagegrab.CheckNormal(); 
           }; 
          pagegrab.CheckNormal(); 
         } 
         else 
         { 
          pagegrab.Elapsed += (obj, e) => 
          { 
           pagegrab.CheckXML(); 
          }; 
          pagegrab.CheckXML(); 
         } 
        } 
        ); 

這很好用,如果我直接使用線程,但真的想更新這些代碼。重複的執行立即發生。 PageGrabber對象非常簡單,它只是簡單地使用WebClient將HTML或XML下載爲字符串 - 非常無聊。

+0

您發佈的哪部分代碼是「最初啓動代碼」?還是那個地方? – svick

+0

缺少的部分是它讀取包含URL的文本文件的部分,並使用它們創建「url」對象。它在try catch塊中。獲取URL,創建一個URL對象,將其添加到URL類型列表,然後是foreach循環 - 就是這樣。這是真正的基本,這是什麼讓我這樣做。這也很難調試,因爲它只發生在大約6個小時內沒有任何東西被觸碰。 – kpcrash

+0

重複執行是否發生爲對來自多個(幾乎)同時線程的請求的響應?或者它是否在一個受控環境中響應一個請求而發生?即你確定封閉的方法沒有被調用2x?我在發佈的代碼中看不到會導致問題的任何內容。 –

回答

3

我認爲問題是,你已經通過pageGrabber.Elapsed +=... 訂閱的Elapsed事件有可能升高或沒有該事件。 因此,在某些情況下,如果事件引發,您的方法將被調用兩次,否則它將被調用一次。

我不認爲你可以通過改變並行實現來解決這個問題(使用任務數組而不是Parallel.Foreach)。這可能會導致問題發生頻率降低,這在並行編程中是非常糟糕的症狀。你不應該讓這些問題通過使他們的前提變得更加困難而消失!你應該完全刪除它們!

+0

我不同意 - 因此對於設置已過期事件的替代方法有何建議?在這種情況下 - 對象中的System.Timers.Timer需要在它自己的Interval上運行。 – kpcrash

+0

@kpcrash我對你的PageGrabber類以及Elapsed事件的責任一無所知。 – mehrandvd

0

所以mehrandvd是在正確的道路上。當創建我的類的一個實例時,它使用了一個System.Timers.Timer,它正在觸發Elapsed事件,因爲Interval屬性沒有被正確設置。因此:

pagegrab.Elapsed += (obj, e) => 
         { 
          pagegrab.CheckXML(); 
         }; 
         pagegrab.CheckXML(); 

引起沒事的時候在一段時間發生了重複執行,因爲有間隔設置正確不再在內存中的類的實例。我的愚蠢 - 現在都已經修好了。感謝所有的意見和建議。

相關問題