0

当我运行这段代码时

      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);
    }

.Net 4.0 和 4.5 版的输出不同。随着 4.0 数字 5 重复,我可以看到 i 的原因值在一些任务执行之前被移动到 5,但是 4.5 的相同代码显示不同的输出。

(输出使用 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**

但是当我使用.Net 4.5(VS 2011 beta)运行时,结果是,

(输出与 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

我看不到 CLR 4.5 下的 Task 所做的更改?谁能指出.Net 4.5的变化是什么。

4

2 回答 2

1

您的代码有竞争条件。假设循环在任何任务开始之前完成执行。这是完全可能的。

然后我在所有任务中的值为 5 。这是错误。

解决方案:将 i 复制到一个循环局部变量并在任务的 lambda 中使用这个局部变量。

于 2012-04-25T18:00:42.800 回答
0

您的代码有竞争条件。这意味着它可以以各种方式运行,具体取决于操作的确切顺序。

而且任何微小的变化都可能影响操作的顺序,所以你的代码在不同版本的框架下会有不同的表现也就不足为奇了。实际上,我希望它在为同一版本的 .net 运行多次时表现不同。

于 2012-04-25T17:09:12.613 回答