所以我有这个相当简单的代码。看一看。
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
方法内。
答案 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。