3

System.Threading.Tasks从一个 for 循环中创建,然后ContinueWith在同一个循环中运行一个。

int[,] referencedArray = new int[input.Length / 4, 5];
   for (int i = 0; i <= input.Length/4; i += 2048)
     {
       int[,] res = new int[input.Length / 4, 5];
       int[,] arrayToReference = new int[input.Length / 4, 5];
       Array.Clear(arrayToReference, 0, arrayToReference.Length);
       Array.Copy(input, i, arrayToReference, 0, input.Length / 4);
       Task<Tuple<int[,], int>> test = Task.Factory.StartNew(() => addReferences(arrayToReference, i));
        test.ContinueWith(t => { Array.Copy(t.Result.Item1, 0, referencedArray, t.Result.Item2, input.Length / 4); MessageBox.Show("yai", t.Result.Item2.ToString()); });
        Array.Copy(res, 0, referencedArray, i, input.Length / 4);

其中 addReference sbroutine 是:

public Tuple<int[,],int> addReferences(int[,] input, int index)
    {
            for (int i = 0; i < 2048; i++)
            {
                for (int j = 0; j < i; j++)
                {
                    if ((input[i, 0] == input[j, 0]) && (input[i, 1] == input[j, 1]) && (input[i, 2] == input[j, 2]) && (input[i, 3] == input[j, 3]))
                    {
                        input[i, 4] = (j - i);
                    }
                }
            }
        }
        return new Tuple<int[,],int>(input,index);
    }

但是,我得到了非常奇怪的结果:

1.索引(在任务启动时从循环计数器生成)不知何故变得太大。我最初认为这是因为循环计数器的增量超过了最大值,从而停止了循环,但是在continueWith执行时它使用了新值。但是,即使我在任务index启动时将循环计数器的值发送给任务,错误仍然存​​在。编辑:已解决

我把原来的计数弄错了

2.由于某种原因,实际完成的任务少于预期(例如,即使预期创建 85 个任务,基于循环计数器最大值 160,000 除以迭代 2,048 = 78,仅出现 77 个弹出窗口) -编辑检查控制台,很明显循环计数器上升到大约 157,696 才突然停止。

我真的对任务和线程感到困惑,所以如果你能提供任何真正有用的帮助 - 在此先感谢。

编辑我已经做出了 Douglas 建议的更改,这解决了我的第一个问题 - 我仍然停留在第二个问题上。

4

1 回答 1

4

这可能无法完全解决您遇到的问题,但作为起点,您需要通过在匿名方法中引用它之前将循环计数器复制到内部变量来避免关闭问题:

for (int i = 0; i <= input.Length/4; i += 2048)
{
    // ...
    int iCopy = i;
    var test = Task.Factory.StartNew(() => addReferences(arrayToReference, iCopy));
    // ...
}

请参阅Jon Skeet 的回答(尤其是链接的文章),了解为什么这是必要的。

编辑:关于你的第二个问题,我怀疑它可能与整数除法有关。input.Length您期望 85 次迭代的值是多少?你说 174,000 除以 2,048 应该得到 85,但实际上,它会得到 84,因为整数除法会导致结果被截断。

编辑2:您没有看到所有预期迭代的另一个原因可能是您的程序正在终止而没有等待任务(通常在后台线程上执行)完成。检查等待任务是否可以解决您的问题:

List<Task> tasks = new List<Task>();
for (int i = 0; i <= input.Length/4; i += 2048)
{
    // ...
    var test = Task.Factory.StartNew(() => addReferences(arrayToReference, iCopy));
    tasks.Add(test);
    // ...
}
Task.WaitAll(tasks);
于 2013-07-05T11:24:53.037 回答