wtf2022 2019-12-13 10:20 采纳率: 0%
浏览 388
已结题

一个奇怪的c#客户端 异步事件调用datagridview控件的问题

我的客户端有两个界面,下面就简称为Form1 和Form2。
Form1有一个datagridview控件,需要有的操作就是在控件里循环载入数据库中的数据并清空再下一轮载入数据。
Form2的功能是监听网络请求并如果收到请求告诉Form1开始工作。
然后问题就来了如果 在Form1 中调用这个操作没有任何问题,如果用Form2调用这个操作的方法(这里是用了一个委托事件触发的,而且因为在调用Form中方法的同时还需要保持监听,所以用线程池做成异步来处理)就会返回main主函数抛出一个空指针异常,但是我断点调试没有找到空指针的对象。异常如图:
图片说明
图片说明

然后上错误代码:
Form1对控件操作:

        public void test()
        {
            Monitor.Enter(this);
            try
            {


            for (int i = 0; i < 7; i++)
            {
                Control.CheckForIllegalCrossThreadCalls = false;
                string fn = list[i];
                OpenDB(fn);
                //Thread.Sleep(1000);


            }

            }
            finally
            {
                Monitor.Exit(this);
            }


        }

         void connectToDB(string fn)
        {
            m_dbConnection = new SQLiteConnection("Data Source=" + fn + ";Version=3;");
            //m_dbConnection.SetPassword("abc");
            m_dbConnection.SetPassword("1234LiaoQiu4321");
            m_dbConnection.Open();
        }

        public void OpenDB(string fn)
        {
            try
            {
                string sql;
                SQLiteCommand command;

                connectToDB(fn);

                sql = @"SELECT * FROM [评分细则] ORDER BY [步骤];";
                command = new SQLiteCommand(sql, m_dbConnection);
                SQLiteDataReader reader = command.ExecuteReader();

                dataGridView2.Rows.Clear();
                object[] obj = new object[10];
                while (reader.Read())
                {
                    for (int i = 0; i < 10; ++i)
                    {
                        obj[i] = reader[i];
                    }
                    dataGridView2.Rows.Add(obj);
                }

                reader.Close();
            }
            catch //(Exception ex)
            {
                MessageBox.Show("打开失败!", "错误", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
            }
            finally
            {
                m_dbConnection.Close();
            }
        }
       /// <summary>
        /// 事件订阅
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void 其他窗口运行ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Form2 ab = new Form2();
            ab.getEvent += test;
            ab.Show();
        }

Form2:

 public delegate void getHandler();
        public event getHandler getEvent;
        private void button1_Click(object sender, EventArgs e)
        {
            ThreadPool.QueueUserWorkItem(new WaitCallback(test), new object());
        }

        public void test(object val)
        {

            getEvent();
        }

Form2这里是我写的一个模拟错误调用的demo,因为监听网络调用调式比较麻烦,所以用button模拟触发 收到消息这个动作。考虑过跨线程调用控件的问题,所以已经加了禁用语句。

问题奇怪的地方有三个:1.如果是Form1本身的线程调用,或者Form2中不加异步就不会抛异常;2,调试时发现循环第一次不会出错,也就是会往控件里加载一次数据,但是第N次循环就可能会出现问题,出错的循环次数是哪一次无法确定,但是肯定会有一次出错。3.报错的位置不在调试时卡住的地方而是回到main主函数报错

而且目前找到一种解决办法就是在循环提内加入延迟,就是Thread.Sleep(500),这样也不会报错,但是不理解这样做就不报错的原因

  • 写回答

2条回答 默认 最新

  • hxycsdn9159 2019-12-13 11:13
    关注

    可能是Form2 ab = new Form2(); 这句代码的问题,不要把ab声明为局部变量,声明称全局变量,如果你声明为局部变量GC有可能就会把它销毁掉造成空引用

    评论

报告相同问题?

悬赏问题

  • ¥20 腾讯企业邮箱邮件可以恢复么
  • ¥15 有人知道怎么将自己的迁移策略布到edgecloudsim上使用吗?
  • ¥15 错误 LNK2001 无法解析的外部符号
  • ¥50 安装pyaudiokits失败
  • ¥15 计组这些题应该咋做呀
  • ¥60 更换迈创SOL6M4AE卡的时候,驱动要重新装才能使用,怎么解决?
  • ¥15 让node服务器有自动加载文件的功能
  • ¥15 jmeter脚本回放有的是对的有的是错的
  • ¥15 r语言蛋白组学相关问题
  • ¥15 Python时间序列如何拟合疏系数模型