繁体   English   中英

为什么此锁语句不起作用

[英]Why this lock statement does not work

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

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

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

因为当其他所有任务都开始时,您的主要任务已完成。 它不会等到他们全部完成 因此,有时您会在所有子任务运行之前捕获result的价值。

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

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

这是一个等待多个任务完成的示例 您将需要WaitAll版本,而不是WaitAny

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

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

暂无
暂无

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

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