foreach識別子とクロージャ
2023-08-27 05:27:58
質問
以下の2つのスニペットにおいて、最初のスニペットは安全ですか、それとも2番目のスニペットを実行しなければなりませんか?
安全というのは、各スレッドが、スレッドが作成されたのと同じループのイテレーションからFoo上のメソッドを呼び出すことが保証されているかということです。
それとも、ループの各反復に新しい変数 "local" への参照をコピーしなければならないのでしょうか?
var threads = new List<Thread>();
foreach (Foo f in ListOfFoo)
{
Thread thread = new Thread(() => f.DoSomething());
threads.Add(thread);
thread.Start();
}
-
var threads = new List<Thread>();
foreach (Foo f in ListOfFoo)
{
Foo f2 = f;
Thread thread = new Thread(() => f2.DoSomething());
threads.Add(thread);
thread.Start();
}
更新しました。 Jon Skeetの回答で指摘されているように、これは特にスレッディングとは関係ありません。
どのように解決するのですか?
編集:これはすべて C# 5 で変更され、変数が(コンパイラから見て)定義される場所が変更されました。以下から C# 5 以降では、それらは同じ .
C#5以前
2番目は安全で、1番目は安全ではありません。
とは
foreach
で、変数が宣言されています。
外
ループの外、つまり
Foo f;
while(iterator.MoveNext())
{
f = iterator.Current;
// do something with f
}
これは、1つしかない
f
のみであり、スレッドが混乱する可能性があります。これを修正するには、2 つ目の変数宣言
内部
ループの内部で
foreach(Foo f in ...) {
Foo tmp = f;
// do something with tmp
}
これは次に、別の
tmp
をそれぞれのクロージャースコープに含めるので、この問題が発生する危険はありません。
以下は、この問題の簡単な証明です。
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();
}
出力する(ランダムに)。
1
3
4
4
5
7
7
8
9
9
temp変数を追加すると動作します。
foreach (int i in data)
{
int j = i;
new Thread(() => Console.WriteLine(j)).Start();
}
(各番号は1回ずつ。もちろん順番は保証されていない)
関連
-
[解決済み] EntityTypeにキーが定義されていないエラー
-
[解決済み】プロセスが実行されているかどうかを知るには?
-
[解決済み] C#のStringとstringの違いは何ですか?
-
[解決済み] C#の正しいバージョン番号を教えてください。
-
[解決済み] C#がforeachで変数を再利用するのは理由があるのか?
-
[解決済み] C#のconstとreadonlyの違いは何ですか?
-
[解決済み] foreachループの現在の反復処理のインデックスを取得するにはどうすればよいですか?
-
[解決済み] クロージャ」と「ラムダ」の違いは何ですか?
-
[解決済み] Swiftでindexとelementでループを反復させる方法
-
[解決済み】JavaScriptのクロージャと無名関数の比較
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】「未割り当てのローカル変数を使用」とはどういう意味ですか?
-
[解決済み】C#で四捨五入する方法
-
[解決済み】パディングが無効で、削除できない?
-
[解決済み】「namespace x already contains a definition for x」エラーの修正方法は?VS2010にコンバートした後に発生しました。
-
[解決済み】WPFでXamlファイルにコメントを追加する方法は?
-
[解決済み】MetadataException: 指定されたメタデータ・リソースをロードできない
-
[解決済み] 2つのリストを結合する
-
[解決済み】名前 'ViewBag' が現在のコンテキストに存在しない - Visual Studio 2015
-
[解決済み】Nullableオブジェクトは値を持たなければならない?
-
[解決済み】.NETの「クロージャ」とは何ですか?