0

When i ran this piece of code

      private void button1_Click(object sender, EventArgs e)
    {
        Start(sender, e);
    }

    private void Start(object sender, EventArgs e)
    {
        for (int i = 0; i < 5; i++)
        {
            System.Threading.Tasks.Task.Factory.StartNew(() => dosomething(i));
            Debug.WriteLine("Called " + i);
        }
        Debug.WriteLine("Finished");

    }
    public void dosomething(int i)
    {
        Debug.WriteLine("Enters " + i);
        lock (this)
        {
            Debug.WriteLine("Working " + i);
            Thread.Sleep(100);
        }
        Debug.WriteLine("Done " + i);
    }

output is different with .Net version 4.0 and 4.5. With 4.0 number 5 is repeated I can see the reason value of i is moved to 5 before some of the Tasks executed but same code with 4.5 shows different output.

(output ran with VS 2010 .Net 4.0)

Called 0
Called 1
Enters 1
Working 1
Called 2
Called 3
Called 4
Finished
Enters 0
Done 1
Enters 5
Working 0
Working 5
Done 0
**Enters 5
Working 5
Done 5
Enters 5
Done 5
Working 5
Done 5**

but when i ran with .Net 4.5 (VS 2011 beta) the result is,

(output ran with VS 2011 beta .Net 4.5)

Enters 0
Working 0
Called 0
Called 1
Enters 2
Called 2
Enters 2
Enters 3
Called 3
Called 4
Finished
Done 0
Working 2
Enters 5
Done 2
Working 3
Done 3
Working 5
Done 5
Working 2
Done 2

I couldn't see changes done with Task under CLR 4.5? Can anyone point me what are the changes with .Net 4.5 please.

2 Answers 2

1

Your code has a race condition. Let's say the loop finishes executing before any of the tasks gets started. This is entirely possible.

Then i will have a value of 5 in all tasks. This is the bug.

Solution: Copy i to a loop-local variable and use this local in the task's lambda.

Sign up to request clarification or add additional context in comments.

3 Comments

Thanks for reply, I do agree changing the code System.Threading.Tasks.Task.Factory.StartNew((object o) => dosomething(i), i); does work properly, my question is not how to make it work but what changes have been done with CLR 4.5?
@murali That question is meaningless. The order is simply undefined, and doesn't need to be consistent between different runs on the same version of the runtime.
I guess the new CLR is more efficient at starting tasks. Because of that the (nondeterministic) order changed. Btw, this is not undefined behavior. It is well-defined but non-deterministic.
0

Your code has a race condition. What that means is that it can behave in various way, depending on the exact order of operations.

And any small change may affect the order of operations, so it's not unexpected that your code will behave differently under different versions of the framework. Actually, I would expect it to behave differently when run multiple times for the same version of .net.

3 Comments

I wouldn't bother about order, I am only looking at i value is shared between the threads with .Net 4.0 but not with .Net 4.5.
The i variable in Start() is shared in both cases, and what exactly happens does depend on the order of operations.
Thanks for you time...So, your point is there is no change with 4.5, the result is different because order of operations? I don't think so, with what reason I am saying this? If you observe order of actions with output you will see only after brief pause the value is affected. and I have tested multiple times and all the time , order is different, but the result is same as shown above...

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.