2011-12-29 75 views
2

背景: 我正在研究已經設計了線程系統的應用程序。這遠非最佳,但我現在不能重做它。它不使用.net中的任何較新的線程構造,只包含基本的Thread對象,以及包裝線程處理邏輯的對象。同步.NET中的多個線程4

的它的一般集合起來就是:(有兩個組,或現在的線程類別)

  • 主應用程序線程(statthread主),其派生的工作線程。

  • 工作線程。每個對象都有一個Thread對象和一個工作對象,它執行所有處理/處理線程之間的邊界等。每個線程運行作業,每個作業有一個JobTypeID

我需要引入第三種類型的線程,一個用於控制工人。這些控制消息將來自一個wcf Web服務(所以這個線程被隱式處理)。

的控制消息是:{暫停/恢復,列表-的-ID的}

我的目標:

我試圖找出最好的方式將這些螺紋,使得同步如果一個線程正在處理一個作業,並且一條消息說要暫停這個JobTypeID的所有作業,它應該阻塞,直到發送一個簡歷(對於該ID)。這裏的問題是,在發送消息時,沒有相關的工作可能正在處理,因此不需要立即採取行動,而且我也沒有工作者對象列表,所以我不能簡單地迭代每個工作人員,然後執行if-matches-then-pause。

實際問題(廣義) 什麼將你們推薦我做了一組工作線程,一個產卵/管理器線程,和一組控制線程的同步?

事情,我已經試過

一種方法是將存儲ManualResetEvent對象,每一個JobTypeID的集合,並且信號,並根據傳入的消息等待他們。你對這種方法有什麼看法?我無法找到任何關於在一個流程中擁有100多個等待句柄的最佳實踐或內存/處理成本的信息。

另一種方法是讓所有線程都等待一個對象,並等待一個同步的JobTypeIDs集合。這種方法我遇到了一些問題。使用ManualResetEvent意味着如果我恢復一個工作ID,但其他人正在等待,我必須做set(); reset();這會導致一些競爭條件(即使我嘗試執行WaitHandle.SignalAndWait(x,x ))最後,我想出了一個使用Monitor.PulseAll()的解決方案。

我也可以使用帶有大量鎖對象的顯示器 - 這看起來像是比許多等待手柄更輕量級。

此外,對於長時間的問題和感謝閱讀!

+0

一些問題: 1.是否每個工作者線程都負責一個JobTypeId?或者每個線程處理任何可用的內容?當暫停消息被接受時,是否可以完全暫停一個線程中的處理作業,或者是否需要它來跳過暫停的作業,但是是否繼續處理其他作業? 2.您有多少工作線程? 3.如果工作線程在暫停消息被接收時處理作業 - 你想讓它完成作業還是暫停它? – ttil 2011-12-29 18:30:41

回答

2

創建一個ConcurrentDictionary<JobTypeId, ManualResetEvent>。通常,JobTypeId將不會在字典中輸入。唯一一個這樣的條目將存在的時候是該工作類型應該被阻止。

當該作業類型應該被阻止時,創建一個不帶信號的ManualResetEvent,並將其添加到詞典中,密鑰爲JobTypeId將被阻止。

工作線程,那麼,有一個循環,看起來像這樣:

while (still_have_work_to_do) 
{ 
    ManualResetEvent mevent; 
    if (PauseDictionary.TryGetValue(myJobTypeId, out mevent)) 
    { 
     // wait until the event is signaled. 
     mevent.WaitOne(); 
    } 

    // Do more processing. 
} 

的產卵線程也可以查詢字典,看它是否能夠產生一個特定類型的工人。如果它不能創建工作人員,那麼它要麼丟棄該工作,要麼重新排隊以便在稍後檢查。你多久進行一次民意調查取決於你。

在單個進程中擁有數百個對象並沒有什麼特別的問題。一堆Monitor對象可能需要更少的系統資源,但請記住Monitor(或lock)確實是一個互斥設備。你可以做一些愚蠢的事情,使其在某些方面像WaitHandle一樣行事,但這些技術並不明顯,這會導致難以理解和脆弱的代碼。