为什么这个锁定语句不起作用

时间:2014-06-11 20:08:13

标签: c# multithreading locking

所以我有这个相当简单的代码。看一看。

var monitor = new object();

var result = 0;

Task.Factory.StartNew(() =>
{
    var childTaskFactory = new TaskFactory(TaskCreationOptions.AttachedToParent, TaskContinuationOptions.ExecuteSynchronously);
    for (int i = 0; i < 5; i++)
    {
        childTaskFactory
            .StartNew<int>(() => CreateRequest()) // this methods just return the integer value 10
            .ContinueWith(task => { lock (monitor) { result += task.Result; } });
    }
}).Wait();

基本上我正在实例化一个用于获取锁的新对象。然后我创建一个int变量,设置为0.之后我创建一个父Task,它将包含5个子Task,所有这些子任务调用一个名为CreateRequest只返回10号(不要介意方法的名称)。每个子Task都有一个继续,它会锁定monitor,并将CreateRequest方法返回的数字10添加到result变量中。在程序结束时,我希望变量result包含值50.但它没有。我的意思是有时它确实有,但有时它被设置为20,30或40.显然我要么误解如何使用lock语句或者实现有问题。很可能我在代码中有一些错误。此代码位于static Main类的Program方法内。

3 个答案:

答案 0 :(得分:4)

因为您的主要任务在所有其他任务开始时完成。它并不等待所有人完成。因此,有时您在所有子任务运行之前都会捕获result的值。

作为测试,在Thread.Sleep(1000)之后添加Wait(),您将看到result按预期更新。但是不要将它用于生产代码。相反,编写等待所有子任务完成的代码。

答案 1 :(得分:1)

如果我正确理解了代码,它实际上并没有等待所有5个任务完成。相反,它等待所有5个任务开始,在此期间显然一个或多个任务可能完成,给你10,20,30或40而不是50。

Here's an example等待完成多项任务。您需要WaitAll版本,而不是WaitAny

答案 2 :(得分:0)

您还可以通过将子任务添加到List中,然后在末尾添加断点来检查发生的情况。然后,如果您在“本地”窗口中检查对象,您将看到某些任务的状态仍为“正在运行”。

请注意,将任务添加到List中可能会影响执行并导致结果更频繁地等于50。