ホームページ >バックエンド開発 >C++ >私の `foreach` ループと Lambda スレッドは C# で安全ですか?

私の `foreach` ループと Lambda スレッドは C# で安全ですか?

Barbara Streisand
Barbara Streisandオリジナル
2025-01-22 07:06:16630ブラウズ

Is My `foreach` Loop and Lambda Threading Safe in C#?

C# の foreach ループとラムダ式のスレッド セーフティの問題

次のコード スニペットを分析してみましょう:

<code class="language-csharp">foreach (Foo f in ListOfFoo)
{      
    Thread thread = new Thread(() => f.DoSomething());
    threads.Add(thread);
    thread.Start();
}</code>
<code class="language-csharp">foreach (Foo f in ListOfFoo)
{      
    Foo f2 = f;
    Thread thread = new Thread(() => f2.DoSomething());
    threads.Add(thread);
    thread.Start();
}</code>

各スレッドがスレッドの作成時と同じループ反復で Foo インスタンスのメソッドを呼び出すことを保証するコード スニペットはどれですか?

C# 5 以降では、クロージャ スコープ内の変数定義に対するコンパイラの変更により、両方のコード スニペットが安全です。ただし、C# 5 より前では、2 番目のスニペットのみが安全でした。

最初のコード スニペットでは、変数 f がループの外で宣言され、実行中ずっと表示されたままになります。これは、クロージャースコープ内に f のインスタンスが 1 つだけあることを意味します。したがって、f にアクセスする異なるスレッドが競合し、メソッド呼び出しエラーが発生する可能性があります。

この問題を軽減するために、2 番目のコード スニペットはループ内で新しい変数 f2 を宣言します。これにより、各クロージャ スコープが Foo インスタンスへの参照の独自のコピーを持つことを保証し、スレッドごとに安全なメソッドの実行を保証します。

次の例は、この問題を示しています。

<code class="language-csharp">static void Main()
{
    int[] data = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };

    foreach (int i in data)
    {
        new Thread(() => Console.WriteLine(i)).Start();
    }

    Console.ReadLine();
}</code>

一時変数が使用されていない場合、このコードは予測できない不正確な出力を生成します。 これは、すべてのスレッドが同じ i 変数を参照し、foreach の値が i ループ終了後の最後の値であるためです。

したがって、スレッドの安全性を確保するには、2 番目のコード スニペットに示すように、foreach ループ内で Lambda 式を使用するときに常にローカル変数のコピーを作成することが最善です。

以上が私の `foreach` ループと Lambda スレッドは C# で安全ですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。