Lambda expressions and captured variables
As we saw, a lambda expression is the most powerfulway to pass data to a thread. However, you must becareful about accidentally modifying captured variablesafter starting the thread, because these variablesare shared. For instance, consider the following:1 for (int i = 0; i < 10; i++) 2 new Thread (() => Console.Write (i)).Start();
The output is nondeterministic! Here’s a typical result:
0223557799 The problem is that the ivariable refers to the samememory location throughout the loop’s lifetime. Therefore, each thread calls Console.Writeon a variable whose value may change as it is running! This is analogous to the problem we describe in “Captured Variables” in Chapter 8 of C# 4.0 in a Nutshell. The problem is less about multithreading and more aboutC#'s rules for capturing variables (which are somewhat undesirable in the case of forand foreachloops). The solution is to use a temporary variable as follows:1 for (int i = 0; i < 10; i++) 2 new Thread (() => Console.Write (i)).Start();
Variable tempis now local to each loop iteration. Therefore, each thread captures a different memory location and there’s no problem. We can illustrate the problem in the earlier code more simply with the following example: string text = "t1"; Thread t1 = new Thread ( () => Console.WriteLine (t ext) ); text = "t2"; Thread t2 = new Thread ( () => Console.WriteLine (t ext) ); t1.Start(); t2.Start();Because both lambda expressions capture the same textvariable, t2is printed twice: t2 t2