Click here to Skip to main content
15,888,401 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
Hello,

I have a code which looks like this :

C#
        static void Main(string[] args)
        {
            List<string> l = new List<string>(250);
            List<thread> t = new List<thread>(250);


    l.Add("a");
    l.Add("b");
    l.Add("c");

    for (int i = 0; i<l.count;i++>            {

                t[i] = new Thread(()=>work(l[i]));  ///Index out of range exception occurrd at this line
                t[i].IsBackground = true;
                t[i].Start();
                
            }

  

    Console.ReadLine();


}

static void work(string data)
{
    Console.WriteLine(data);
}

/// That exception goes away if is say : t[i] = new Thread(()=>work(l[i-1]));
/// But its a bug and does not process records properly.

Please help

[edit]Code block added - OriginalGriff[/edit]
Posted
Updated 25-Dec-13 21:45pm
v3

1 solution

First off, if you are going to post code, then post exactly the code that give you the problem - copy and paste it. The fragment you show isn't that: it won't compile because "thread" is not the same as "Thread" as far as C# is concerned. When you re-type it to end up with "something similar" which may or may not demonstrate the problem.

The problem is that things start to get a little hairy when you play with threads and anonymous delegates - because threads do not execute when you think they will, and if you start passing variable to delegates, you need to be sure what you are passing...

Try this instead (It's a cut down version of yours:
C#
static void Main(string[] args)
    {
    List<string> l = new List<string>(250);
    l.Add("a");
    l.Add("b");
    l.Add("c");

    for (int i = 0; i < l.Count; i++)
        {
        string s = l[i];
        Console.WriteLine("UI Thread: {0}:{1}", i, s);
        Thread nt = new Thread(() => Console.WriteLine("Delegate : {0}:{1}", i, s));
        nt.IsBackground = true;
        nt.Start();
        }
    Console.ReadLine();
    }
And look what you get:
CSS
UI Thread: 0:a
UI Thread: 1:b
UI Thread: 2:c
Delegate : 2:a
Delegate : 2:b
Delegate : 3:c

What? How did that happen?
Pretty simple: the integer is a Value type, which means that the variable itself is passed to the delegate rather than a reference to the variable. So it isn't the number it "contains" that is passed, it is the variable that holds the value. Which means that the value it holds is not examined until the thread itself runs - which may be at any time after the Thread.Start method has been called, depending on how many cores you have and whet else is going on in the system at that time.

In your code, that means that the value of "i" is not retrieved until after the loop ends sometimes, which means that it is outside the range of the list - and you get an exception.

Want to see how to "cure" this?
C#
static void Main(string[] args)
    {
    List<string> l = new List<string>(250);
    l.Add("a");
    l.Add("b");
    l.Add("c");

    for (int i = 0; i < l.Count; i++)
        {
        string s = l[i];
        Console.WriteLine("UI Thread: {0}:{1}", i, s);
        int j = i;
        Thread nt = new Thread(() => Console.WriteLine("Delegate : {0}:{1}:{2}",i, j, s));
        nt.IsBackground = true;
        nt.Start();
        }
    Console.ReadLine();
    }
Now run that...:laugh:



"Sir,
A doubt:
below is just a pseudo code: a generic class, its constructor will be created only if the type parameter is an Enum.

C#
class custom_dictionary<t>
     {
         static public custom_dictionary()////this statement could be wrong
         {
              if(!typeOf(T).IsEnum)
                 ////throw new argument not enum exception
         }

}



- I have used a static constructor here, what if i used an instance constructor?
- How do both vary from each other? and what about constraints to check if the type is Enum?

Thanks,
- Rahul"


First off, Is a static constructor going to work? Think about it: when is a static constructor executed, how often, and what happens if you have two instances of your class with different enums?

Second, there is a mechanism for doing that at compile time: Generic Constraints:
C#
public class custom_dictionary<T> where T : Enum
    {
    }
What that does is says to the compiler: "This is a generic class, but I can only work with enums: if he tries to declare me with an int or a Textbox, tell him not to bother"
And it does:
C#
custom_dictionary<StringSplitOptions> cd = new custom_dictionary<StringSplitOptions>();
Is fine, but
C#
custom_dictionary<int> cd = new custom_dictionary<int>();
Will give you a "there is no boxing conversion" compiler error.

This is a lot, lot better than trying to do this at run time, because it moves the checking into the compiler - so your problem shows up much earlier: before you have coded for a couple of days and have to throw it all away the first time you test it!
 
Share this answer
 
v2
Comments
Rahul VB 26-Dec-13 4:36am    
Respected Sir,
just one thing: you are a genius!!!!!!!!!!!!!
I have started the PLC-PC communication, if you remember me speaking to you earlier. This i did using backgroundworker as you told me. I implemented the ping pong mechanism in the server. I will look into the sensor threading part now. I hope you remember me speaking to you about this. Just wish me luck.
Thanks a lot,
OriginalGriff 26-Dec-13 4:44am    
Please, feel free to tell my wife! :laugh:

Of course I remember - it wasn't that long ago - good luck!
Rahul VB 26-Dec-13 4:47am    
Respected Sir,
I wont lie but i am awake since last night. I just want to give a successful demonstration to my client. I will just finish one more module and dose off.
Thanks again,
Rahul
OriginalGriff 26-Dec-13 4:58am    
Sleep well!
Rahul VB 31-Dec-13 12:54pm    
hello sir,
There are 2 aspects i am thinking about:
1)What can happen if i initialize a thread within a thread?(just a thought)
2)My project is almost on the brink of being deployed, so any tips on optimizing the code?
- I also have to add logging mechanism(just to debug the code, to check hex packets on the socket).
- My team mates tell me to use the File class,my manager says use FileStream and StreamWritter to do all that stuff and are also insisting to use database.
- If i do all such stuff it is definite that my application will slow down.
- According to my friend : first read the sensor data: log it into the file and write important sensor information to the database.
-Out of frustration i have stopped coding, they are behaving like nagging wives and now i am jotting down what can happen if i listen to them.

The main thing is smoking cigarettes and giving ideas is very easy but optimizing the code is a different story hahaha. well i respect both of them, but please advise thanks.

Thanks and regards,
Rahul

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