在单线程中的 List.Add 过程中,什么可能导致“目标数组不够长”?

2024-04-22

我有一个要添加到嵌套 foreach 循环中的对象列表。该操作是同步的(或者也许我并不像我认为的那样理解 lambda)并且是单线程的,并且列表并不是不合理的大。我完全不知道可能导致此异常的原因。

public string PromotionSpecificationIdGuid { get; set; }
public virtual List<ElementInstance> ElementInstances { get; set; }

public void UpdateInstanceGraph(OfferingInstance parentData, OfferingInstance offeringContainer = null)
{
    ElementInstances = new List<ElementInstance>();

    parentData.ActiveServices.ForEach(
        service => service.ActiveComponents.ForEach(
            component => component.Elements.ForEach(
                element =>
                {
                    if (element.PromotionId == this.PromotionSpecificationIdGuid)
                    {
                        ElementInstances.Add(element);
                    }
                })));
}

结果是:

System.ArgumentException: Destination array was not long enough. Check destIndex and length, and the array's lower bounds.
       at System.Array.Copy(Array sourceArray, Int32 sourceIndex, Array destinationArray, Int32 destinationIndex, Int32 length, Boolean reliable)
       at System.Collections.Generic.List`1.set_Capacity(Int32 value)
       at System.Collections.Generic.List`1.EnsureCapacity(Int32 min)
       at System.Collections.Generic.List`1.Add(T item)

试图通过一些单元测试来解决这个问题并对其进行锤炼,但我希望有人可以同时帮助我。

-EDIT-

感谢胡安和马克,我已经弄清楚这是如何发生的。在我的应用程序中,此操作本身是单线程的,但它本质上使用单例并通过 ajax 调用。多个调用者可以启动自己的线程,当这些调用足够接近时,我们就会得到这种行为。我制作了一个控制台应用程序来说明这个概念。

using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;

namespace listaccessmonster
{
    public class Program
    {
        private static List<Guid> baseList = new List<Guid>();
        private static List<Guid> activeList;
        private static Random rand = new Random();

        public static void Main(string[] args)
        {
            for(int i = 0; i < 1000000; i++)
            {
                baseList.Add(Guid.NewGuid());
            }

            var task1 = UpdateList(); //represents ajax call 1
            var task2 = UpdateList(); //represents ajax call 2

            var result = Task.WhenAll(task1, task2);

            try
            {
                result.Wait();
            }
            catch(Exception e)
            {
                Console.WriteLine(e);
            }

            task1 = UpdateListFixed(); //represents ajax call 1
            task2 = UpdateListFixed(); //represents ajax call 2

            result = Task.WhenAll(task1, task2);

            try
            {
                result.Wait();
            }
            catch (Exception e)
            {
                Console.WriteLine(e);
            }

            Console.WriteLine("press Enter to exit");
            Console.ReadKey();
        }

        private static Task UpdateList()
        {
            return Task.Run(()=> {
                Thread.Sleep(rand.Next(5));
                Console.WriteLine("Beginning UpdateList");
                activeList = new List<Guid>();
                baseList.ForEach(x => {
                    activeList.Add(x);
                });
            });
        }

        private static Task UpdateListFixed()
        {
            return Task.Run(() => {
                Thread.Sleep(rand.Next(5));
                Console.WriteLine("Beginning UpdateListFixed");
                var tempList = new List<Guid>();
                baseList.ForEach(x => {
                    tempList.Add(x);
                });
                activeList = tempList;
            });
        }
    }
}

大多数情况下都会引发异常或类似的异常,但并非每次都会引发。它永远不会用固定方法抛出。


你是对的。操作列表的代码不使用线程。

然而,我认为有东西在召唤UpdateInstanceGraph在之前的运行有机会完成之前重复进行(从而引入线程)。那会导致ElementInstances重置为大小0而之前的调用仍在执行。

更改代码以使用本地实例,然后设置公共属性:

public void UpdateInstanceGraph(OfferingInstance parentData, OfferingInstance offeringContainer = null)
{
    var instances = new List<ElementInstance>(); 

    parentData.ActiveServices.ForEach(
        service => service.ActiveComponents.ForEach(
            component => component.Elements.ForEach(
                element =>
                {
                    if (element.PromotionId == this.PromotionSpecificationIdGuid)
                    {
                        instances.Add(element);
                    }
                })));
    ElementInstances = instances;
}

我还建议使用SelectMany相反并投射到List对于直接分配给该属性:

public void UpdateInstanceGraph(OfferingInstance parentData, OfferingInstance offeringContainer = null)
{

    ElementInstances  = parentData.ActiveServices
        .SelectMany(s => s.ActiveComponents)
        .SelectMany(c => c.Elements)
        .Where(e => e.PromotionId == PromotionSpecificationIdGuid).ToList();
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在单线程中的 List.Add 过程中,什么可能导致“目标数组不够长”? 的相关文章

随机推荐

  • unity3d - 加速度计灵敏度

    我正在 Unity3D 4 3 中测试加速度计代码 我想做的就是在倾斜 ipad 的同时简单地改变物体角度 以像真实生活一样伪造视角 一切工作正常 除了加速计有点太敏感 即使我把它放在桌子上 我也可以看到游戏对象在闪烁 如何让它不那么敏感
  • 如何使用 MiniProfiler.Settings.CustomUITemplates

    再会 我在上一篇文章以及上一篇文章中都看过这里http miniprofiler com http miniprofiler com 但找不到任何有关如何使用的文档MiniProfiler Settings CustomUITemplate
  • Hibernate 排序依据最后为空

    Hibernate 与 PostgreSQL DB 一起使用时 按列对 desc 进行排序时 空值会高于非空值 SQL99 标准提供关键字 NULLS LAST 来声明空值应低于非空值 使用 Hibernate 的 Criteria API
  • 如何在 Django REST Framework 上启用 CORS

    如何在 Django REST Framework 上启用 CORS 这参考 http www django rest framework org topics ajax csrf cors 没有多大帮助 它说我可以通过中间件来完成 但我该
  • syn队列和accept队列的混淆

    在阅读TCP源码时 我发现一个困惑的事情 我知道 TCP 在 3 次握手中有两个队列 第一个队列存储服务器收到的连接SYN并发回ACK SYN 我们称之为同步队列 第二个队列存储3WHS成功并建立连接的连接 我们称之为接受队列 但在阅读代码
  • 用于多浏览器测试的 Specflow 的 DataSource 属性

    我有一些 C 中的 Web ui 测试 这些测试是通过 browserstack 中的 selenium 执行的 目前 这些只是简单的单位毫秒测试 它们是在不同的浏览器上执行的 我想将测试移植到specflow 但我真的不知道如何进行多浏览
  • Python http.client.RemoteDisconnected

    尝试使用 python 通过 Web 服务运行多个 ID 我收到 http client RemoteDisconnected 远程端关闭连接而没有响应 错误 我不想尝试 捕获此错误 我想调查为什么会收到此响应 我已经能够得到 400 和
  • java填充系统属性的源码有哪些

    Through System getProperty 字符串键 http docs oracle com javase 7 docs api java lang System html getProperty java lang Strin
  • Angular2测试表单:未调用提交方法

    有了这个组件 import Component from angular2 core import FORM DIRECTIVES from angular2 common Component selector something temp
  • 如何使用 ConfigurationBuilder 绑定到配置类

    我想用ConfigurationBuidler阅读我的appsettings json文件 我看不出我做错了什么 我的文件是 comment this gets copied to bin debug on build the app up
  • Java JFormattedTextfield 时间格式化

    我在代码中使用时间时遇到了一些麻烦 txtDauer new JFormattedTextField txtDauer setFormatterFactory new DefaultFormatterFactory new DateForm
  • 尝试让 POST 返回 400 错误请求

    我有一个通过关联构建新模型的 create 方法 如果 POST 请求中没有参数 我希望它返回带有一些文本的 400 响应 但是 我收到错误 这是在 Rails 4 0 2 中 控制器方法 def create cast profile c
  • jQuery - .children().size() 更改时触发事件

    我已经搜索了近和远 但我不知道如何在子元素的 size 上放置侦听器 我想做的是 我有一个包含 0 6 个以上子元素的 div 这个数字没有定义 因为我正在制作一个购物车 我希望有一个侦听器 而不是每个可以更改购物车中的商品数量的按钮 即添
  • 来自 json 数据的 Padrino 模型

    我一直在为我正在从事的一个项目寻找 Padrino 它似乎非常适合 因为我理想情况下希望支持以 json 形式发送和接收数据 但是我想知道是否有任何内置的自动化帮助程序或功能可以从发布请求 或其他请求 中获取数据并将该数据放入模型中 而无需
  • IIS8 Express 上的 SqlRoleProvider

    我的 Web 应用程序 WCF 服务 使用SqlRoleProvider 这适用于Visual Studio 开发服务器 将其切换到IIS8 Express导致它抛出一个NullReferenceException though Roles
  • pandas HDFStore - 如何重新打开?

    我使用以下方法创建了一个文件 store pd HDFStore home data h5 并使用以下方法存储一些表 store firstSet df1 store close 我关闭了python并在一个新的环境中重新打开 我如何重新打
  • 使用Python的Requests模块登录ASP网站

    我试图从我的学校页面上抓取一些信息 但我很难通过登录 我知道有类似的线程 我花了一整天的时间阅读 但无法使其发挥作用 这是我使用的程序 用户名和密码已更改 import requests payload ctl00 cphmain Logi
  • 按值对 Javascript 对象进行排序

    在我的 Javascript 应用程序中 我有一个对象 我需要能够通过内部对象中的值对数组进行排序 例如 a timestamp xxxxxx other yyyyyy b timestamp xxxxxx other yyyyyy c t
  • 如何检查数组的某一项是否具有真值

    在对象数组中 如何检查任何数组项是否具有 true 属性 我有一个对象数组 我需要检查数组项中是否有一个属性 其值确实是 const arr name Tony test false name Jack test false name Ti
  • 在单线程中的 List.Add 过程中,什么可能导致“目标数组不够长”?

    我有一个要添加到嵌套 foreach 循环中的对象列表 该操作是同步的 或者也许我并不像我认为的那样理解 lambda 并且是单线程的 并且列表并不是不合理的大 我完全不知道可能导致此异常的原因 public string Promotio