Kalpesh said:
Pete,
Thanks for your reply.
Pardon my ignorance - but it outputs the same thing on the machine
that I am on.
What outputs the same thing? What is the actual output? For which
version of the code?
If that's the case, how to really see them outputting different
results (in order to produce the bug)?
The easiest thing would be to include a call to Thread.Sleep() at the
beginning of the anonymous method, to ensure that the rest of the code
in the anonymous method doesn't execute until the main thread has
finished initializing all of the threads.
An alternative would be to use an additional loop. Currently the code
has two: one initializes and starts each thread, while the second waits
for each to complete. You could break the first loop into two different
loops, one of which initializes each thread, another to actually start
each thread. That would reproduce the problem reliably as well.
Also, in real life case -how to make sure that problems like this dont
pass by & get caught when in production?
Well, as a start: very VERY suspicious any time you use a variable
inside an anonymous method that was declared outside that anonymous
method, and the anonymous method is going to be executed asynchronously
relative to the code that's declaring the anonymous method.
The most common reasons for using an anonymous method involve it being
executed asynchronously, so this winds up meaning that you should simply
be suspicious any time a variable is used inside an anonymous method.
One notable exception to this would be using an anonymous method in a
call to Control.Invoke(). But otherwise, asynchronous scenarios are
typical.
By "suspicious", I don't mean you shouldn't do it. I just mean that you
should consider that to be an enormous red flag, requiring very careful
inspection of the code so that you understand exactly what it's doing.
IMHO, if you take the time to really stop and think about what
"capturing" a variable means, then any time you write an anonymous
method this will be very much in the front of your mind. I think
there's a tendency to read and write code in anonymous methods as if the
captured variable exists in the same context as the declaration of the
anonymous method. But it doesn't have to be that way; just remember
that the captured variable's value is used at the same time as the rest
of the code in the anonymous method is _executed_, and you should be
able to avoid these problems.
Pete