What is the difference between:
new Thread(new ThreadStart(SomeFunc))
and:
new Thread( delegate() { SomeFunc();} )
This code gives strange outputs on my computer:
public class A
{
int Num;
public A(int num)
{
Num = num;
}
public void DoObj(object obj)
{
Console.Write(Num);
}
public void Do()
{
Console.Write(Num);
}
}
/////// in void main()
for (int i = 0; i < 10; i++)
{
(new Thread(new ThreadStart((new A(i)).Do))).Start(); // Line 1
(new Thread(new ThreadStart(delegate() { (new A(i)).Do(); }))).Start(); // Line 2
(new Thread(delegate() { (new A(i)).Do(); })).Start(); // Line 3
}
If only Line 1 is executed the output is something like:
0 2 3 1 5 6 4 7 8 9
which is ok but if Line 2 or 3 is executed, output is:
3 3 3 5 5 7 7 9 9 10
There are some multiple numbers and a 10 which is quite strange that the loop is never run with the number 10. What is the trick behind these?
Thanks.
In C#, simply specify the name of the thread procedure. The compiler selects the correct delegate constructor. For C++, starting with . NET Framework 2.0, creating a ThreadStart delegate for a static method requires only one parameter: the address of the callback method, qualified by the class name.
Thread(ThreadStart) Constructor is used to initialize a new instance of a Thread class. This constructor will give ArgumentNullException if the value of the parameter is null.
With the delegate, you are capturing i
.
The difference is that with new ThreadStart((new A(i)).Do))
, you are creating a new instance of A
in the for
loop with i
as a parameter. That means that at that point, the value of i
is taken and send to the constructor. The delegate you are sending is thus not of the creation of A
, but you are actually sending the a delegate of the Do
method of the instance of A
to the constructor.
However, with delegate() { (new A(i)).Do(); })
(both of them), you are sending a reference of i
to the thread.
The thread then takes some time to start and meanwhile, the for
loop goes on. By the time i
is used in the delegate (i.e. the thread has started), the for
loop has moved on to 3
and that's what you see. The same goes for the second and third thread. The three threads are started but wait for the starting thread to complete some work. Then the created threads kick in (thread 1, 2 and 3) and they do their work. The Windows goes back to the thread with the for
loop and goes on to start thread 4 and 5.
Some reading material:
To answer your first point, delegate() { SomeFunc();}
creates a function that calls SomeFunc()
, whereas not using delegate()
simply uses the SomeFunc
function directly as the ThreadStart
method.
In your second question, you're running into the implementation details of C# anonymous functions. All three references to i
refer to the same i
, which is incremented three times. You've got a race condition between the three functions that mean i
can be incremented several times before the started threads are run.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With