3

アクションを実行するスレッドのプールを管理するクラスを使用しています。もともとはアクション(パラメーターなし)を取るようにコーディングされていて、次のように呼び出していました:

void LoadTasks()
{
   string param;

   // some code loops and changes param
   {
      threadPool.EnqueueTask(() => SomeMethod(param));
   }
}

スレッドが実行されたとき、いくつかは問題ありませんでしたが、param 変数が予期したものではない場合がありました...それは「新しい」値であり、メソッドに送信するつもりだったものではありませんでした。

スレッドプールを受け入れるように変更しAction<Object>、ラムダなしで呼び出します-このようにthreadPool.EnqueueTask(SomeMethod, param)-私の問題を回避しました。

スレッド セーフに関する C# ラムダについて、かなりの数の質問があります。たとえば、ラムダの受け入れられた回答は、予想よりもスレッドセーフである可能性がはるかに低くなります。 ラムダ/クロージャー/スコーピングに関する他の質問と回答がわかりにくいと感じています。したがって、ラムダと可変スコープの説明を探しています。理想的には、私の例の問題に関連しています。

4

1 に答える 1

2

したがって、問題は、意図しない変数を閉じていることです。ほとんどの場合、新しいローカル変数を作成し、一度閉じていた変数をコピーしてから、代わりにそれを閉じることで簡単に修正できます

したがって、代わりに:

for(int i = 0; i < number; i++)
{
    threadPool.EnqueueTask(() => SomeMethod(someList[i]));
}

あなたはただ行うことができます:

for(int i = 0; i < number; i++)
{
    int copy = i;
    threadPool.EnqueueTask(() => SomeMethod(someList[copy]));
}

現在、各ラムダは、同じ 1 つの変数ですべてを閉じるのではなく、独自の変数で閉じています。

于 2013-07-10T15:29:59.380 に答える