for 循环以创建超过结束条件的任务

本文关键字:结束 条件 任务 循环 创建 for | 更新日期: 2023-09-27 18:34:38

我有一个 for 循环来创建许多被计量的任务:

int count = 16;
List<Tuple<ulong, ulong>> brackets = GetBrackets(0L, (ulong)int.MaxValue, count);
Task[] tasks = new Task[count];
s.Reset();
s.Start();
for(int i = 0; i < count; i++)
{
    tasks[i] = Task.Run(() => TestLoop(brackets[i].Item1, brackets[i].Item2));
}
Task.WaitAll(tasks);
s.Stop();
times.Add(count, s.Elapsed);

但是,当它运行时,For 循环内的行会引发异常,该括号 [i] 不存在,因为此时 i 是 16,即使循环设置为在 i 计数时运行<。

如果我将行更改为:

tasks[i] = new Task(() => TestLoop(brackets[0].Item1, brackets[0].Item2));

然后不会引发任何错误。此外,如果我遍历带有断点的循环,则不会引发任何问题。

对于重现,我还包括 GetBrackets,它只是将数字范围分解为块:

private List<Tuple<ulong, ulong>> GetBrackets(ulong start, ulong end, int threads)
{
    ulong all = (end - start);
    ulong block = (ulong)(all / (ulong)threads);
    List<Tuple<ulong, ulong>> brackets = new System.Collections.Generic.List<Tuple<ulong, ulong>>();
    ulong last = 0;
    for (int i=0; i < threads; i++)
    {
        brackets.Add(new Tuple<ulong, ulong>(last, (last + block - 1)));
        last += block;
    }
    // Hack
    brackets[brackets.Count - 1] = new Tuple<ulong, ulong>(
        brackets[brackets.Count - 1].Item1, end);
    return brackets;
}

谁能对此有所了解?

for 循环以创建超过结束条件的任务

(这是类似帖子的副本,但它们通常很难找到,症状通常略有不同。

问题是你正在捕获循环中的变量i

for(int i = 0; i < count; i++)
{
    tasks[i] = Task.Run(() => TestLoop(brackets[i].Item1, brackets[i].Item2));
}

您有一个 i 变量,lambda 表达式会捕获它 - 因此当您的任务实际开始执行 lambda 表达式中的代码时,它可能不会具有与以前相同的值。您需要在循环中引入一个单独的变量,以便每次迭代捕获不同的变量:

for (int i = 0; i < count; i++)
{
    int index = i;
    tasks[i] = Task.Run(() => TestLoop(brackets[index].Item1, brackets[index].Item2));
}

或者,使用 LINQ 创建任务数组:

var tasks = brackets.Select(t => Task.Run(() => TestLoop(t.Item1, t.Item2));
                    .ToArray(); // Or ToList