Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/320.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 为什么这个lock语句不起作用_C#_Multithreading_Locking - Fatal编程技术网

C# 为什么这个lock语句不起作用

C# 为什么这个lock语句不起作用,c#,multithreading,locking,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 <

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

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();
var monitor=新对象();
var结果=0;
Task.Factory.StartNew(()=>
{
var childTaskFactory=new TaskFactory(TaskCreationOptions.AttachedToParent,TaskContinuationOptions.ExecuteSynchronously);
对于(int i=0;i<5;i++)
{
儿童任务工厂
.StartNew(()=>CreateRequest())//此方法只返回整数值10
.ContinueWith(task=>{lock(monitor){result+=task.result;}});
}
}).Wait();

基本上,我正在实例化一个用于获取锁的新对象。然后我创建一个
int
变量,该变量设置为0。之后,我将创建一个父
任务
,其中将包含5个子
任务
s,所有这些子任务调用一个名为
CreateRequest
的方法,该方法只返回一个数字10(不介意方法的名称)。每个子
任务
都有一个continuation,它获取
监视器
上的锁,并将
CreateRequest
方法返回的数字10添加到
结果
变量中。在程序结束时,我希望变量
result
包含值50。但事实并非如此。我的意思是有时会,但有时会设置为20、30或40。显然,要么我误解了如何使用
lock
语句,要么实现有问题。很可能我的代码有错误。此代码位于
程序
类的
静态主
方法中。

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


作为测试,将
线程.Sleep(1000)
放在
等待()之后,您将看到
结果按照预期更新。但不要将其用于生产代码。相反,编写等待所有子任务完成的代码。

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


作为测试,将
线程.Sleep(1000)
放在
等待()之后,您将看到
结果按照预期更新。但不要将其用于生产代码。更确切地说,编写等待所有子任务完成的代码。

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


等待多个任务完成。您需要的是
WaitAll
版本,而不是
WaitAny

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


等待多个任务完成。您需要的是
WaitAll
版本,而不是
WaitAny

您还可以通过将子任务添加到列表中,然后在末尾添加断点来检查发生了什么。如果随后检查“局部变量”窗口中的对象,您将看到某些任务的状态仍在运行


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

您还可以通过将子任务添加到列表中,然后在末尾添加断点来检查发生了什么。如果随后检查“局部变量”窗口中的对象,您将看到某些任务的状态仍在运行


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

除了到目前为止的答案所指出的要点之外,我还注意到此代码不必要地复杂。如果您打算启动五项任务,然后同步等待所有任务完成,则创建一个包含五项任务的数组,用五项启动的任务填充该数组,然后调用
Task.WaitAll
,传递该数组。这只是一个示例代码。除了到目前为止答案中给出的要点之外,我还注意到这个代码是不必要的复杂。如果您打算启动五个任务,然后同步等待所有任务完成,则创建一个包含五个任务的数组,用五个启动的任务填充该数组,然后调用
Task.WaitAll
,传递该数组。这只是一个示例代码。一本书指出,如果我要等待父任务,子任务也将等待。显然不是。这本书还建议使用Task.Run进行子连接,但我知道Task.Run拒绝子连接,@Dima,如果您使用
async/await
这本书是正确的。你知道AttachedToParent是做什么的吗?你确定你需要它吗?不知道。这本书没有说明任何关于async/wait的内容。一本书说如果我等待父任务,子任务也会等待。显然不是。这本书还建议使用Task.Run进行子连接,但我知道Task.Run拒绝子连接,@Dima,如果您使用
async/await
这本书是正确的。你知道AttachedToParent的功能吗?你确定你需要它吗?不知道。这本书没有说明任何关于async/await的内容