2011-10-11 27 views
6

外の変数は、このコードを取ることができます:ラムダ式は、マルチスレッド

public void Hit(int npage) 
     { 
      bool fetch = false; 
      lock (pagesHit) 
      { 
       if (!pagesHit.Contains(npage)) 
       { 
        pagesHit.Add(npage); 
        fetch = true; 
       } 
      } 
      if (fetch) 
      { 
       pageFiller.Completed += (s, e) => 
        { 
         lock (pagesHit) 
         { 
          pagesHit.Remove(npage); 
         } 
        }; 
      } 

     } 

この機能は、異なるスレッドから呼び出すことができます。目標は、すでにフェッチ予定のページを取得することを避けることです。フィラーオブジェクトは、ラムダ式を介して購読されているイベントを公開します。私の質問です:パラメータnpageがマルチスレッドシナリオで正しく処理されていると言えますか?より良い:各イベントサブスクリプションは、npageパラメータを受信するか、最後にnpageがすべてのイベントに伝播しますか?

答えて

7

の宣言スコープnpageで発生します。パラメータnpageはメソッドレベルで宣言されており、そのメソッド内では変更されません。実際、npageの使用はであり、完全にスレッドセーフです。

あなたはループ一般的に、その宣言のスコープ内変数を変更した場合に生じる避けている問題 - すなわち

for(int npage = 0; npage < 100 ; npage++) 
    Foo((s,e) => DoSomething(npage)); // not safe; npage shared between all 

しかし、この方法にそれを壊すことによって、あなたがこの問題を回避する、すなわち

for(int i = 0; i < 100; i++) 
    Hit(i); 
... 
void Hit(int npage) { 
    Foo((s,e) => DoSomething(npage)); // safe; npage is per-call 
} 
2

それぞれHitメソッド呼び出しは、npageの参照で異なる値を持ちます。

つまり、このメソッドを呼び出す各スレッドは、独自のnpageを持ちます。

これは、このメソッドを呼び出すスレッドごとに、操作とイベントハンドラのサブスクリプションが異なるスコープで行われるため、npage参照はスコープの値を指しているからです。