Home >Backend Development >C++ >Why Do Foreach Loops and Closures Require Special Handling in Multithreaded C# Code?
Understanding foreach Loops and Closures in Multithreaded C#
Multithreading in C# can introduce complexities when using foreach
loops and closures. The problem arises when a closure within a foreach
loop references the loop's iteration variable.
Consider this example:
<code class="language-csharp">var threads = new List<Thread>(); foreach (Foo f in ListOfFoo) { Thread thread = new Thread(() => f.DoSomething()); threads.Add(thread); thread.Start(); }</code>
Here, each thread's closure captures a reference to the single f
variable. As the loop progresses, f
's value changes, leading to unpredictable results—threads might operate on unexpected Foo
objects.
Ensuring Thread Safety
To avoid this, create a new local variable within each iteration:
<code class="language-csharp">var threads = new List<Thread>(); foreach (Foo f in ListOfFoo) { Foo f2 = f; // Create a copy for each thread Thread thread = new Thread(() => f2.DoSomething()); threads.Add(thread); thread.Start(); }</code>
Now, each thread has its own independent reference (f2
), ensuring that DoSomething()
is called on the correct Foo
instance.
C# 5 and Beyond
The behavior changed slightly in C# 5 and later. The compiler treats the foreach
variable as effectively declared within the loop's scope, even though it appears outside. Therefore, both code snippets above are thread-safe in C# 5 and subsequent versions. However, the explicit copy remains good practice for clarity and backward compatibility.
The above is the detailed content of Why Do Foreach Loops and Closures Require Special Handling in Multithreaded C# Code?. For more information, please follow other related articles on the PHP Chinese website!