2

为什么这不是每一个都完成?相反,它会引发异常,就像未捕获异常一样。此外,异常“索引超出数组范围”对我来说没有意义。

        int n = 3;
        string[] names = new string[] { "sally", "fred", "gina" };
        Task[] myTasks = new Task[n];
        for (int y = 0; y < n; y++)
        {
            myTasks[y] = Task.Factory.StartNew(() =>
            {
                Action<string> action = (name) =>
                {
                    try
                    {
                        throw new Exception(name + ", I bet you can't catch me.");
                    }
                    catch (Exception e)
                    {
                        //I caught you... didn't I?
                    }
                };
                action(names[y]);
            });
        }

        Task.WaitAll(myTasks);
        Console.WriteLine("All tasks complete.");//This line is never reached;
4

2 回答 2

8

括号内的 lambda 函数StartNew正在形成一个闭包,该闭包“捕获”外部变量“ y”......它不会访问它的值......在循环迭代期间......相反,当捕获在该 lambda 函数中访问变量......那是它试图获取值的时候。

您的“ y”变量最终达到值“3”(通过循环y++)......因为这会导致“用于创建“动作”的循环)......退出(即 3 不小于 3 )。

但是,当Task您创建的任何 s 正在执行该行时action(names[y]),它正在访问已关闭的变量“ y”......“可能”已经达到“3”......并且“3”不是数组中的有效索引....这完全取决于这些任务的安排速度有多快或多慢,以及您是否遇到问题……经典的竞争条件。

于 2014-08-16T18:59:32.530 回答
1

我确实通过在任务之外设置一个变量来确定名称

var name = names[y];

并使用它而不是从任务中访问数组,它可以工作。我还是不明白为什么。

于 2014-08-16T18:39:19.347 回答