首页 / 浏览问题 / 组件GIS / 问题详情
ob6遍历加载地图崩溃的问题
2EXP 2018年04月07日

使用产品:SuperMap Objects 6 操作系统:win8 x64
数据类型: 文件型
问题详细描述:开始的5次左右加载正常,但是次数多就直接崩溃了,调试时出现最多的问题是(尝试读取或写入受保护的内存。内存已损坏。),现在不提示错误了,直接崩溃了
问题重现步骤: 1.不断勾选图层10次左右

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using SuperMapLib;//添加引用
using System.Runtime.InteropServices;//添加引用
using System.Collections;//集合引用

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        #region 打开数据源文件
        private void button1_Click_1(object sender, EventArgs e)
        {
            //打开按钮事件
            //问题一,用户选定文件
            //设置对话框
            OpenFileDialog openFileDialog1 = new OpenFileDialog();
            openFileDialog1.Title = "我是标题";
            openFileDialog1.Filter = "sdd文件|*.sdd;*sdb;|所有文件|*.*";
            openFileDialog1.InitialDirectory = Application.StartupPath;
            //DialogResult dlgRuslut = openFileDialog1.ShowDialog();
            if (openFileDialog1.ShowDialog() == DialogResult.OK)
            {
                //用户按的是打开按钮
                //问题2,得到用户选定的文件全路径
                //问题3,核心方法打开
                //工作空间控件.opendatasource()-数据源对象sodatasource

                //先关闭再打开
                axSuperWorkspace1.Close();
                string sourcefile = openFileDialog1.FileName;
                textBox1.Text = sourcefile;
                textBox1.ReadOnly = true;
                list_item();
                axSuperWorkspace1.Close();
            }
        }
        #endregion

        #region 在checklistbox中列出项目的方法
        
        public void list_item()
        {
            checkedListBox1.Items.Clear();
            axSuperWorkspace1.Close();
            soDataSource soDatasource = axSuperWorkspace1.OpenDataSource(textBox1.Text, "sdd", seEngineType.sceSDBPlus, false);
            if (soDatasource != null)
            {
                soDatasets soDatasets = soDatasource.Datasets;//数据集,集合对象

                for (int i = 1; i <= soDatasets.Count; i++)
                {
                    checkedListBox1.Items.Add(soDatasets[i].Name);//同理在复选框中列出数据集名称
                }
            }
            else
            {
                MessageBox.Show("打开数据源失败!", "提示");
            }

        }
        #endregion

        #region 遍历加载选中的图层的方法
       
        public void xuanzhong()
        {
            axSuperWorkspace1.Close();
            axSuperMap2.Close();
            axSuperMap2.Refresh();
            ConnectSuperMap();
            soDataSource soDatasource = axSuperWorkspace1.OpenDataSource(textBox1.Text, "sdd", seEngineType.sceSDBPlus, false);
                soDatasets soDatasets = soDatasource.Datasets;//数据集,集合对象
                soLayer oblayer2;
                for (int i = 0; i < checkedListBox1.CheckedIndices.Count; i++)
                {
                    int k = i + 1;
                    oblayer2 = axSuperMap2.Layers.AddDataset(soDatasets[k], false);
                }
                axSuperMap2.Refresh();


        }
        #endregion
        #region 工作空间与地图连接,句柄连接的方法
        
        private void ConnectSuperMap()   //自定义函数,用来关联控件
        {
            //关联SuperMap控件
            object objHandle = axSuperWorkspace1.ObjectHandle;    //工作空间控件句柄
            axSuperMap2.Connect(objHandle);
            Marshal.ReleaseComObject(objHandle);
            objHandle = null;

        }
        #endregion

        #region 勾选事件
        
        private void checkedListBox1_SelectedIndexChanged(object sender, EventArgs e)
        {
            checkedListBox1.CheckOnClick = true;
            xuanzhong();
        }
        #endregion
    }


    }

萌新尝试很多次了,望大神指导一下,万分感激!

1个回答

您好,看了一下代码,工作空间和地图的关闭使用不恰当,工作空间只有当不用到该工作空间任何资源的时候,才做关闭的处理,而您使用的数据是同一个工作空间数据源下面的,地图也是同一个工作空间下面,但是你每向地图添加一个图层的时候都关闭了工作空间,显然是不对的。地图的使用也是如此,只有切换地图的时候,才会去关闭当前地图,看您的需求,显然是不需要做这一步的。所以建议您优化以下代码,另外弄清楚产品的数据组织(主要是工作空间,数据源,地图,图层,数据集之间的关系)。
胡林
1
5,985EXP 2018年04月08日

cool好的,非常感谢,我再摸索一下

大神您好,我修改了一下代码,现在正常加载地图不崩溃了,但是在移除图层的时候还是会崩溃

即   axSuperMap2.Layers.RemoveAll();//加了这段代码就又出错了

我想实现显示勾选的数据集组成的地图,不钩就不显示。请问应该如何实现

代码如下:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using SuperMapLib;//添加引用
using System.Runtime.InteropServices;//添加引用
using System.Collections;//集合引用

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {

        public Form1()
        {
            InitializeComponent();
            
        }

        #region 打开数据源文件

        private void button1_Click_1(object sender, EventArgs e)
        {
            //打开按钮事件
            //问题一,用户选定文件
            //设置对话框
            OpenFileDialog openFileDialog1 = new OpenFileDialog();
            openFileDialog1.Title = "我是标题";
            openFileDialog1.Filter = "sdd文件|*.sdd;*sdb;|所有文件|*.*";
            openFileDialog1.InitialDirectory = Application.StartupPath;
            //DialogResult dlgRuslut = openFileDialog1.ShowDialog();
            if (openFileDialog1.ShowDialog() == DialogResult.OK)
            {
                //用户按的是打开按钮
                //问题2,得到用户选定的文件全路径
                //问题3,核心方法打开
                //工作空间控件.opendatasource()-数据源对象sodatasource

                //先关闭再打开
                axSuperWorkspace1.Close();
                string sourcefile = openFileDialog1.FileName;
                textBox1.Text = sourcefile;
                textBox1.ReadOnly = true;
                string strAlias = System.IO.Path.GetFileNameWithoutExtension(textBox1.Text);
                soDataSource soDatasource = axSuperWorkspace1.OpenDataSource(textBox1.Text, strAlias, seEngineType.sceSDBPlus, false);
                soDatasets soDatasets = soDatasource.Datasets;//数据集,集合对象
                soLayer solayer2 = null;
                list_item(soDatasets, solayer2);
            }
        }
        #endregion


        #region 在checklistbox中列出项目的方法
        public void list_item( soDatasets soDatasets, soLayer oblayer2)
        {
            
            checkedListBox1.Items.Clear();
                for (int i = 1; i <= soDatasets.Count; i++)
                {
                    checkedListBox1.Items.Add(soDatasets[i].Name);//同理在复选框中列出数据集名称
                }

        }
        #endregion

        #region 工作空间与地图连接,句柄连接的方法
        
        private void ConnectSuperMap()   //自定义函数,用来关联控件
        {
            //关联SuperMap控件
            object objHandle = axSuperWorkspace1.ObjectHandle;    //工作空间控件句柄
            axSuperMap2.Connect(objHandle);
            axSuperWkspManager1.Connect(objHandle);
            Marshal.ReleaseComObject(objHandle);
            objHandle = null;

        }
        #endregion


        private void button2_Click(object sender, EventArgs e)
        {
           
            axSuperMap2.Refresh();
        }

        private void checkedListBox1_SelectedValueChanged(object sender, EventArgs e)
        {
            //axSuperMap2.Layers.RemoveAll();//加了这段代码就又出错了
            checkedListBox1.CheckOnClick = true;
            ConnectSuperMap();
            string str = System.IO.Path.GetFileNameWithoutExtension(textBox1.Text);
            soDataSources objDss = this.axSuperWorkspace1.Datasources;
            soDataSource objDs = objDss[str];
            soDatasets soDatasets = objDs.Datasets;//数据集,集合对象
            soLayer oblayer2;
            soLayers soblayers = this.axSuperMap2.Layers;
            axSuperMap2.Refresh();

            for (int n = 0; n < checkedListBox1.Items.Count; n++)
                if (checkedListBox1.GetItemChecked(n))
                {
                    foreach (int s in checkedListBox1.CheckedIndices)
                    {
                        int k = s + 1;
                        oblayer2 = axSuperMap2.Layers.AddDataset(soDatasets[k], false);
                    }
                }
                else
                    return;
        }

    }


    }

想实现显示勾选的数据集组成的地图,不钩就不显示。通过移除图层的方式去实现的话,略显粗糙,可以判断控件当前状态是否被选中,然后设置对应的图层是否可见即可,即layer.visible实现,只有当用户想移除图层的时候,再去做移除图层的操作。
明白了,非常感谢!
...