0

我遇到的问题似乎与任务创建有关。在使用循环填充任务数组并在单独的循环中启动它们之后,我的结果虽然一致,但还是错误的。但是,如果我单独填充数组,在循环中启动每个任务,一切都很好。任何人都可以给我一些建议吗?

例如,这是有问题的:

int c = 1;
for (int i = 1; i <= 4; i++)
    {
       taskArray[i-1] = new Task(() => calculateRows(c, true));
       c = c + 2;
    }
foreach (Task t in taskArray) t.Start();

但这很好用:

taskArray[0] = new Task(() => calculateRows(1, true));
taskArray[1] = new Task(() => calculateRows(3, true));
taskArray[2] = new Task(() => calculateRows(5, true));
taskArray[3] = new Task(() => calculateRows(7, true));
foreach (Task t in taskArray) t.Start();
4

1 回答 1

6

问题是您的 lambda 表达式捕获c-变量 c,而不是创建任务时的值。因此,当您启动任务时,c将是 9。即使您在循环中启动它们,仍然不能保证 lambda 表达式中的代码将更改为c.

要解决此问题,您可以为循环的每次迭代使用单独的局部变量:

int c = 1;
for (int i = 1; i <= 4; i++)
{
    int temp = c;
    taskArray[i-1] = new Task(() => calculateRows(temp, true));
    c = c + 2;
}
foreach (Task t in taskArray)
{
    t.Start();
}

或完全绕过c并计算tempi

for (int i = 1; i <= 4; i++)
{
    int temp = i * 2 - 1;
    taskArray[i-1] = new Task(() => calculateRows(temp, true));
}
foreach (Task t in taskArray)
{
    t.Start();
}

你需要这些都是单独的任务吗?你可以Parallel.For改用吗?或者也许Enumerable.Range正如评论中所建议的那样:

var tasks = Enumerable.Range(1, 4)
                      .Select(x => new Task(() => calculateRows(x * 2 - 1, true)
                      .ToArray();
foreach (Task t in tasks)
{
    t.Start();
}
于 2013-09-03T21:01:29.657 回答