Click here to Skip to main content
15,886,788 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
Well, I am bit new to concept of threads. I am at my initial stages of experimenting with it. I wrote the following code to see how threads placed in a list would execute.

C#
using System;
using System.Threading;
using System.Collections.Generic;

namespace ConsoleApp
{
    class Program
    {
        static object obj = new object();
        static void Main(string[] args)
        {
            List<Thread> threadList = new List<Thread>();
            for (int i = 0; i < 10; i++)
            {
                threadList.Add(new Thread(() => ExecuteThread($"{ i }")));
            }

            foreach (var thread in threadList)
            {
                thread.Start();
            }
            return;
        }

        public static void ExecuteThread(string name)
        {

            Console.WriteLine($"In thread {name}");
            lock (obj)
            {
                Console.WriteLine($"Inside the lock of thread {name}.");
                Console.WriteLine("Waiting for keypress....");
                Console.ReadKey();
            }

            return;
        }
    }
}


And I received the following OUTPUT :

In thread 10
In thread 10
In thread 10
In thread 10
In thread 10
In thread 10
In thread 10
In thread 10
In thread 10
In thread 10
Inside the lock of thread 10.
Waiting for keypress....
Inside the lock of thread 10.
Waiting for keypress....
Inside the lock of thread 10.
Waiting for keypress....
Inside the lock of thread 10.
Waiting for keypress....
Inside the lock of thread 10.
Waiting for keypress....
Inside the lock of thread 10.
Waiting for keypress....
Inside the lock of thread 10.
Waiting for keypress....
Inside the lock of thread 10.
Waiting for keypress....
Inside the lock of thread 10.
Waiting for keypress....

-------

Why does it show "Inside the lock of thread 10." instead of "Inside the lock of thread i" ? What feature of threads am I not understanding with this output ?

(With 'i', I mean the value of the i specified in the loop.)

What I have tried:

I had tried finding the instant values each variable using the debugger, but that was not of much help here.
Posted
Updated 26-Feb-20 4:05am

1 solution

The delegate you pass to the Thread constructor captures a local variable. When you create the delegate in a for loop, each delegate shares a reference to the same captured variable. The value of that variable will reflect the value of the captured variable when the delegate is executed, not the value when the delegate was created.

To avoid this, you need to capture a copy of the loop variable:
C#
for (int i = 0; i < 10; i++)
{
    int iCopy = i;
    threadList.Add(new Thread(() => ExecuteThread($"{iCopy}")));
}
There's a discussion of this on StackOverflow:
closures - Captured variable in a loop in C# - Stack Overflow[^]
 
Share this answer
 
v2
Comments
Richard MacCutchan 26-Feb-20 11:05am    
I figured that was happening but could not give a proper explanation. And i am still confused as to how the delegate can still reference the variable since it only exists in the for loop.
Richard Deeming 26-Feb-20 11:10am    
The variable gets hoisted to a field in a closure class by the compiler.
Unobviousness in use of C# closures[^]
Richard MacCutchan 26-Feb-20 11:21am    
Yes, I followed that link to SO and read the explanation. Now I need a lie down.
flareduser 27-Feb-20 1:41am    
Just saw the link you had referred to. How is List<Action> valid when Action itself is a method in DisplayClass in the for-loop example?
Richard Deeming 27-Feb-20 6:01am    
Action is a delegate. When a delegate points to an instance method, it captures the instance of the class that it's pointing to, which is stored in the delegate's Target property.

NB: This can create a memory leak if you have a delegate pointing to an instance method of a class, and the delegate's lifetime is significantly longer than the intended lifetime of the class.

Delegates - C# Programming Guide | Microsoft Docs[^]
Open Delegates vs. Closed Delegates – SLaks.Blog[^]

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900