2012-01-26 10 views
0

私のアプリケーションには、バックグラウンドスレッドのコレクション内のアイテムの処理を実行するオブジェクトがあります。オブジェクトが作成されると、コレクション内のすべての既存のアイテムのバックグラウンド処理をスレッドプール使用してトリガーされます。コレクション内のアイテムのバックグラウンド処理と新しいアイテムの追加(スレッドプールを使用)

class CollectionProcessor 
{ 
    public CollectionProcessor() 
    { 
     // Not actually called during the constructor just put it here to simplify the code sample 
     Action process = new Action(this.Process); 
     createIndex.BeginInvoke(true, ar => process.EndInvoke(ar), null); 
    } 

    void Process() 
    { 
     for (int i = 0; i < this.items.Count; i++) 
     { 
      this.ProcessItem(this.items[i]); 
     } 
    } 
} 

が通知コールバックの周りに点在いくつかの余分なコードがあるが、それは主に、それの要旨です。

新しいアイテムをいつでもこのコレクションに追加することができます。これらの新しいアイテムが処理されていることを確認する必要があります。新しいアイテムの通知は、アイテムがコレクションに既に追加された後に発生するイベントによって提供されます。 。このイベントのイベントhanlderで、私はに必要なもしながら、非同期コレクション内の新しいアイテムの処理を再開:私は同じ項目を処理していないことを確認

  • 二回
  • その項目を確保正しい順序私もスレッドプールを使用する代わりに、専用のスレッドを使用してこれを達成したいブロックされたバックグラウンドタスク

がたくさん並ん回避

  • で処理されている - 私はこれをどのようにするべきですか?this.itemsへのアクセスがスレッドセーフであることは明らかです。

  • +0

    同期化されたキューを使用して、処理が開始されたらオブジェクトをリストに移動できませんか? – Lloyd

    +0

    @Lloydコレクションへのアクセスはすでにスレッドセーフです。私の質問は、非同期的に 'Process' – Justin

    答えて

    0

    私はこれを行うための合理的にきちんとした方法を考え出したと思います。これらのキーは、私は、この処理を行う専用のバックグラウンドスレッドを持っていたならば、解決策は非常に簡単であり、このように少し見えるかもしれないことに注意することです。

    AutoResetEvent ev = new AutoResetEvent(false); 
    
    // Called on a background thread 
    void ThreadProc() 
    { 
        int lastProcessed = 0; 
        while (true) 
        { 
         // Perform our processing as before 
         for (int i = lastProcessed; i < this.items.Count; i++) 
         { 
          this.ProcessItem(this.items[i]); 
         } 
    
         // We have processed all items currently in the list, wait for some more 
         ev.WaitOne(); 
        } 
    } 
    
    void OnNewItems() 
    { 
        ev.Set(); 
    } 
    

    ミッシングリンクは、私たちはこれを変換することができますThreadPool.RegisterWaitForSingleObject Methodです

    int lastProcessed = 0; 
    
    void StartProcessing() 
    { 
        ThreadPool.RegisterWaitForSingleObject(
         this.ev, 
         new WaitOrTimerCallback(WaitProc), 
         null, // All state stored in the class instance itself 
         -1,  // Always wait indefinitely for new items 
         true // Only execute once - each callback registers a new wait handle ensuring 
           // that a maximum of 1 task is running Process at any one time 
        ); 
    } 
    
    void WaitProc(object state, bool timedOut) 
    { 
        // Perform our processing as before 
        for (int i = lastProcessed; i < this.items.Count; i++) 
        { 
         this.ProcessItem(this.items[i]); 
        } 
    
        // We have processed all items currently in the list, wait for some more 
        this.StartProcessing(); 
    } 
    

    これは、リセットイベントを待機しているスレッドをブロックしていないことを除いて、ループを前と同じように設定します。

    関連する問題