I am new to c# and multithreading concept and was exploring multithreading. I am getting unexpected output. Following is the program I wrote in c#:-
static void Main(string[] args)
{
for (int i = 1; i <= 5; i )
{
System.Threading.Thread workerThread = new System.Threading.Thread(() => fn(i));
workerThread.Start();
}
System.Console.WriteLine("!End the main process!");
}
public static void fn(int x)
{
System.Console.WriteLine($"fn method called for {x}");
System.Threading.Thread.Sleep(5000);
for (int i = 1; i <=2 ; i )
{
System.Console.Write($" {x} ");
}
}
Expected Output:- One of the expected output would have been:-
- !End the main process!
- fn method called for 1
- fn method called for 2
- fn method called for 3
- fn method called for 4
- fn method called for 5
- 1 1 2 2 3 3 4 4 5 5
Actual Output what I am getting is:-
- !End the main process!
- fn method called for 4
- fn method called for 3
- fn method called for 2
- fn method called for 5
- fn method called for 2
- 2 2 2 4 2 4 3 3 5 5
Why the function fn was called twice of 2 and why it wasn't called for 1?
and when I re-run the function I am getting
- !End the main process!
- fn method called for 3
- fn method called for 4
- fn method called for 3
- fn method called for 6
- fn method called for 4
- 3 3 3 3 4 4 6 4 6 4
How did fn end up getting called for 6?
CodePudding user response:
Because you are passing i
as an argument, it depends on what the value of i
is at the specific moment the method is executed. If the method doesn't get executed until your loop has moved on to the next iteration, it will get the incremented value of i
.
The solution is to not use a variable that has that outer scope. Declare a local variable specifically for the method argument:
for (int i = 1; i <= 5; i )
{
var arg = i;
System.Threading.Thread workerThread = new System.Threading.Thread(() => fn(arg));
workerThread.Start();
}
arg
is allocated anew for each iteration so every method call will get the correct value of arg
.