c# - Task.WaitAll 索引越界异常原因

标签 c# task aggregateexception

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

        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;

最佳答案

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

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

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

关于c# - Task.WaitAll 索引越界异常原因,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25342671/

相关文章:

c# - 如何使用 C# 解析从 Google Insights 下载的 CSV

c# - 我可以直接使用 Entity Framework 生成的模型吗?

c# - Task.Run vs Task.Factory.StartNew - 没有发生预期的死锁

c# - 为什么我的 try/catch block 没有捕获 System.AggregateException?

c# - 扁平化聚合异常以进行处理

c# - 为什么 Entity Framework 添加了 '...Id' 字段?

c# - 使用不同的 InMemory 数据库仍然增加身份

c# - 何时使用 Task.Run 而不是

c# - 在哪里处理 Task 抛出的异常

c# - 使用任务保持 UI 响应,处理 AggregateException