2013-10-07 54 views
2

我在我的C#應用​​程序中有一個靜態的共享資源(文本處理器類)集合,它響應關鍵字。每個處理器都是有狀態的,所以不能在多線程環境中工作。我正在尋找一種組織這些的好方法,以便我可以對其進行線程安全訪問。同步C#中的共享資源集合

例如,我可以嵌入一個同步對象中的每個處理器

public abstract class TextProcessor 
{ 
    protected internal readonly object sync = new object(); 

    public abstract void Run(string text); 
} 

public class DocumentProcessor 
{ 
    private static Dictionary<string,TextProcessor> s_procMap = ...; 

    public void Run(string [] words1, string[] words2) 
    { 
     ThreadPool.QueueUserWorkItem(Process, words1); 
     ThreadPool.QueueUserWorkItem(Process, words2); 
    } 

    private void Process(object arg) 
    { 
     foreach(var word in words) 
     { 
      var proc = s_processor[word]; 
      lock(proc.sync) 
      { 
       proc.Run(word); 
      } 
     } 
    } 

假設我不能重寫我的處理器是無狀態(這是一個選項,但會是最後的手段,由於體積重構),有沒有更好的方式來表達這一點?

+0

「TextProcessor」是所有處理器的超類嗎? –

+1

不知道爲什麼你需要在這裏多線程?似乎所有的同步問題可能會導致所有性能優勢的喪失,並顯着增加代碼的複雜性。 –

+0

@SergeyRybalkin文本處理造成的時間超過了所需的啓動時間,所​​以我熱衷於調查場景以減輕這種情況。分析顯示我的輸入分析是一個瓶頸,所以我在這裏試圖精簡它。 –

回答

1

如果你真的不想改變處理器...那麼我會做一個包裝。

public class ProcWrapper 
{ 
    private TextProcessor _proc; 
    private ActionBlock<string> _actBlock; 

    public ProcWrapper(TextProcessor proc) 
    { 
    _proc = proc; 

    _actBlock = new ActionBlock<string[]>(word=> 
    { 
     _proc.Run(word); 
    }); 
    } 

    public void AddWord(string words) 
    { 
    _actBlock.Post(word); 
    } 

    public void WaitForCompletion() 
    { 
    _actBlock.Completion.Wait(); 
    } 
} 

而且用它類似於你怎麼收到了它:

Dictionary<string,ProcWrapper> s_procMap = ...; 

void Run(string [] words) 
{ 
    // NOTE: This assumes the same thread will access s_procMap. 
    foreach(var word in words) 
    s_procMap[word].AddWord(word); 
} 

我認爲這是接近你在找什麼。

有關DataFlow的更多信息,請參閱http://msdn.microsoft.com/en-us/library/hh228603.aspx,其中TPLhttp://msdn.microsoft.com/en-us/library/hh194684.aspx的信息與ActionBlock<T>相關。

2

目前的方法的問題是,一個繁忙的TextProcessor可以停止處理剩餘的單詞。如果您改爲給每個TextProcessor一個(線程安全的)單詞隊列,那麼您可以在不阻塞的情況下排隊工作,並讓TextProcessor按順序出隊並處理這些單詞。

TPL Dataflow libraryActionBlock。它處理排隊,從處理Task開始,並在最後關閉Task以防萬一沒有剩餘工作。

注意,當沒有工作排隊時,沒有線程被阻塞。這是一個重要的可擴展性屬性。

+0

http://msdn.microsoft.com/en-us/library/hh228603.aspx供參考。 – Andrew