简体   繁体   English

为什么此锁语句不起作用

[英]Why this lock statement does not work

So I have this fairly simple code. 所以我有这个相当简单的代码。 Take a look. 看一看。

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

Basically I am instantiating a new object to be used for acquiring lock. 基本上,我实例化了一个用于获取锁的新对象。 then I am creating an int variable which is set to 0. After that I am creating one parent Task which will contain 5 child Task s and all of those child task call a method called CreateRequest which just return a number 10 (don't mind the name of the method). 然后我将创建一个设置为0的int变量。之后,我将创建一个父Task ,其中将包含5个子Task ,所有这些子任务都调用一个名为CreateRequest的方法,该方法只会返回数字10(不要介意方法的名称)。 Each child Task has a continuation which acquires lock on the monitor and just adds number 10 returned by the CreateRequest method to the result variable. 每个子Task都有一个延续,该延续获得了monitor锁定,并且仅将CreateRequest方法返回的数字10添加到result变量中。 At the end of the program I expect the variable result to contain the value 50. But it does not. 在程序结束时,我希望变量result包含值50。但事实并非如此。 I mean sometimes it does but some times it is set to 20, 30 or 40. Apparently either I am misunderstanding how to use lock statement or there is something wrong with the implementation. 我的意思是有时这样做,但有时将其设置为20、30或40。显然我误解了如何使用lock语句,或者实现存在问题。 Most probably I have some mistake in a code. 我很可能在代码中有一些错误。 This code is inside the static Main method of the Program class. 此代码在Program类的static Main方法内部。

Because your main task completes when all of the other tasks have started. 因为当其他所有任务都开始时,您的主要任务已完成。 It doesn't wait for them all to finish . 它不会等到他们全部完成 So sometimes you're capturing the value of result before all of the child tasks have run. 因此,有时您会在所有子任务运行之前捕获result的价值。

As a test, put a Thread.Sleep(1000) after the Wait() , and you'll see that result is updated as expected. 作为测试,将Thread.Sleep(1000)放在Wait() ,您将看到result按预期更新。 But don't use that for production code. 但是不要将其用于生产代码。 Rather, write code that waits for all of the child tasks to finish. 而是编写等待所有子任务完成的代码。

If I understand the code correctly, it's not actually waiting for all 5 tasks to complete. 如果我正确理解代码,则实际上并没有等待所有5个任务完成。 Instead, it's waiting for all 5 tasks to be started, during which time apparently one or more of the tasks may complete, giving you 10, 20, 30, or 40 rather than 50. 相反,它等待所有5个任务开始,在此期间,显然一个或多个任务可能完成,从而为您提供10、20、30或40,而不是50。

Here's an example of waiting on more than one task to complete. 这是一个等待多个任务完成的示例 You'll want the WaitAll version, not the WaitAny . 您将需要WaitAll版本,而不是WaitAny

You can also examine what is happening by adding the child tasks into a List and then adding a breakpoint at the end. 您还可以通过将子任务添加到列表中,然后在末尾添加断点来检查正在发生的情况。 If you then examine the objects in the Locals window you will see that the status of some tasks will still be Running. 如果然后在“本地”窗口中检查对象,则会看到某些任务的状态仍为“正在运行”。

Note that adding the tasks into a List may affect the execution and cause the result to equal 50 more often. 请注意,将任务添加到列表中可能会影响执行,并导致结果更频繁地等于50。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM