【问题标题】:ArcGIS crash on memory allocation in C#ArcGIS 在 C# 中的内存分配崩溃
【发布时间】:2010-11-17 09:56:10
【问题描述】:

我正在为 ArcGIS 开发一个将与 ArcView 集成的自定义工具。该工具使用 C# 开发,基本上连接到 SQL 数据库,将数据提取到本地数据结构,执行大量统计分析,然后将结果显示为新层。

在此代码执行期间发生崩溃。

LinkedList<SegmentDbRecord> segmentData = new LinkedList<SegmentDbRecord>();
while( dataReader.Read() )
{
  SegmentDbRecord record = new SegmentDbRecord();

  record.first_stop_id = dataReader.GetInt32(0);
  record.first_stopway = dataReader.GetString(1);
  record.first_stopway_X = dataReader.GetString(2);

  record.second_stop_id = dataReader.GetInt32(3);
  record.second_stopway = dataReader.GetString(4);
  record.second_stopway_X = dataReader.GetString(5);

  record.segment_start = Tools.timeToFloat((DateTime)dataReader.GetValue(6));
  record.segment_finish = Tools.timeToFloat((DateTime)dataReader.GetValue(7));

  record.stop1_long = dataReader.GetFloat(8);
  record.stop1_lat = dataReader.GetFloat(9);
  record.stop2_long = dataReader.GetFloat(10);
  record.stop2_lat = dataReader.GetFloat(11);

  record.max_speed = dataReader.GetInt32(12);
  record.avg_speed = dataReader.GetInt32(13);
  record.route_hnd = dataReader.GetInt32(14);
  record.seq_1 = dataReader.GetInt32(15);
  record.seq_2 = dataReader.GetInt32(16);
  record.route_name = dataReader.GetString(17);

  segmentData.AddFirst(record);

}

在这个阶段,我只是将查询的结果保存在一个链表中。我很确定崩溃发生在内存分配期间,但我知道仍然有大量内存剩余,并且查询没有返回如此大的数据集。运行一个分配新“记录”的简单循环也会很快崩溃。你们中有人知道 ArcGIS 运行时中的内置保护可以阻止我分配超过一定数量的内存吗?

谢谢!

【问题讨论】:

  • 我在这段代码中没有任何与 ArcGIS 相关的内容。您如何确定这是 ArcGIS 问题?您收到的确切错误消息是什么?
  • 如果您能向我们展示所抛出异常的 ToString() 将会有所帮助。
  • 我收到来自 ArcGIS 的崩溃并显示以下消息:“ArcGIS Desktop 遇到严重的应用程序错误,无法继续”我没有收到任何具体消息...只有发送邀请错误报告。我确实得到了一个“转储”文件,但它似乎不可用。
  • ArcGIS 是否使用非 .NET 组件?
  • 如果我理解 Decapsuleur 的问题,他正在为 ArcMap 创建一个用 C++/COM 编写的插件。同样,ArcMap 的加载项是 COM DLL,所以这将是我们正在讨论的 COM 项目(如果我正在关注这个问题)。

标签: c# .net memory-management arcgis


【解决方案1】:

我找到的解决方案是在不同的线程中进行所有处理。我的工具的结构方式是,按钮事件正在向“作业处理程序”发送命令(让我们这么称呼它,我不会分享我不那么原始的内部类名),它会立即执行它(因为没有其他工作已安排)。我认为由于内存分配花费的时间太长,ArcGIS 将 COM DLL 视为无响应,并通过在没有任何迹象的情况下简单地崩溃来处理这种情况。

感谢大家一直以来提供的有用答案。

【讨论】:

    【解决方案2】:

    可能是数据转换问题。以这一行为例:

    record.max_speed = dataReader.GetInt32(12);
    
    • max_speed 是 int32 吗?
    • 位置 12 的字段是可以转换为 int32 的值吗?

    你可以做的是注释掉所有分配值的行,看看它是否运行,然后一次添加一行,看看哪一行导致错误。

    编辑

    根据评论,问题似乎是由于使用了 LinkedList。为什么不直接使用 List?

    【讨论】:

    • 没有分配码问题依旧出现。只需分配内存并在列表中添加记录就足以使程序崩溃。
    • 我在分配了 17969 条记录后发生了崩溃。这大约是 1 MB 的数据。
    • 查看事件日志,查看应用程序池是否正在回收
    • 我该如何检查?另外,我使用 List 也遇到了同样的问题。我使用 LinkedList 是因为我想避免调整数组的大小,因为它往往很昂贵。
    • 转到管理工具 -> 事件日志,看看是否在运行代码的同时写入了任何错误。您是否有显示抛出异常的文本?
    【解决方案3】:

    很久以前,我们在 Arc GIS 中遇到过类似的神秘崩溃问题。我们最终发现在服务器端为 Arc GIS 帐户启用了磁盘配额。删除配额解决了这个问题。

    如果其他方法不起作用,您可以尝试一下。

    【讨论】:

    • 我不确定我是否理解您所说的服务器。
    • 我相信 amazedsaint 说的是 ArcGIS Server,而不是 ArcMap。
    【解决方案4】:

    ArcMap 悄悄地吞下用户添加组件的异常。捕获和处理代码中发生的任何异常由您决定。

    一种简单的故障排除技术包括将整个代码块包装在如下内容中:

    try {
        ... 
    } catch (Exception ex) { 
        MessageBox.Show(ex.ToString());
        throw;
    }
    

    希望您能收到信息丰富的消息。

    【讨论】:

      猜你喜欢
      • 2010-11-14
      • 1970-01-01
      • 2016-10-09
      • 1970-01-01
      • 2020-10-05
      • 1970-01-01
      • 2011-08-02
      • 1970-01-01
      • 2021-04-01
      相关资源
      最近更新 更多