2

したがって、List<myObj> のディクショナリを取得し、ディクショナリのキーを循環して、各 List<myObj> を別のスレッドに渡すメソッドがあります。

ここにいくつかのコード/擬似コードがあります:

public static void ProcessEntries() {

    Dictionary<string, List<myObj>> myDictionary = GetDictionary();

    foreach(string key in myDictionary.keys)
    {

        List<myObj> myList = myDictionary[key];

        Thread myThread = new System.Threading.Thread(new System.Threading.ThreadStart(delegate() {

            ProcessList(myList);

        }    
    }
}

public static void ProcessList(List<myObj> myList) {

    // Process entries
    // read-only operations on myList

}

問題は、ProcessList の実行中に myList パラメータが単純に変更されることです。

スレッドをキックする前にリストをループし、すぐにスレッド内でループしましたが、結果が異なることがわかりました。

その後、Dictionary 変数をグローバルにすることで問題を解決しました (と思います!)。[ThreadStatic] プロパティの使用は、可能な修正のリストの次です。

私が本当に知りたいのは、おそらく myList オブジェクトが ProcessEntries() で再割り当てされたときに、 ProcessList() 内で myList オブジェクトが変更されるのはなぜですか? これらは 2 つの異なる List ではありませんか? すべてのパラメーターの受け渡しがデフォルトで値渡しである場合、 ProcessList() 関数が myList のローカル コピーを持たないのはなぜですか? (そうですか?)

パラメータをスレッドに渡し、実行中に親スレッドまたは他のスレッドによって変更されないように指定する方法はありますか? (これは、グローバル変数の [ThreadSafe] 属性に似ています)

4

3 に答える 3

2

あなたの疑似コードは、実際には実際のコードを正確に反映していないと思います。あなたの実際のコードは次のようになっていると思います。

foreach(var pair in myDictionary)
{
    Thread myThread = new Thread(delegate() {
        ProcessList(pair.Value);
    });
    myThread.Start();
}

その場合、問題はpair変数がキャプチャされていることです。そのため、スレッドが開始されるまでに、別のキーと値のペアを参照している可能性があります。

これを修正する方法は、コードを疑似コードに正確に近づけることです。

foreach(var pair in myDictionary)
{
    // You'll get a new list variable on each iteration
    var list = pair.Value;
    Thread myThread = new Thread(delegate() {
        ProcessList(list);
    });
    myThread.Start();
}

詳細については、これに関する Eric Lippert のブログ投稿を参照してください。

これが問題でない場合は、疑似コードではなく実際の例を示してください。問題を示す短いが完全な例が理想的です。

于 2010-08-05T17:02:25.587 に答える
1

また、使用しようとしているスレッドが他のスレッドの影響を受けないようにしてください。必ずロックとモニターを使用してください... ほんの数週間前にいくつかの問題がありました..

于 2010-08-06T19:27:12.303 に答える
0

その場合、値で参照を渡しているため、どこかで変更すると、どこでも異なります。

于 2010-08-05T16:53:05.260 に答える