zoukankan      html  css  js  c++  java
  • 在创建窗口句柄之前,不能在控件上调用 Invoke 或 BeginInvoke

    今天关闭一个窗体,报出这样的一个错误"在创建窗口句柄之前,不能在控件上调用 Invoke 或 BeginInvoke。",这个不用多想,肯定是那个地方没有释放掉。
    既然碰到这个问题,先不说问题本身,来说说其他的一些事情。
    winform最常见的是datagridview这个控件,不管重写还是怎么,很多数据的操作都是用datagridview来展示的,因此,它的异步调用也算是比较多的一类了。
    比如:
    1 从数据库中读取大量数据(所谓的分页读取不在这个范畴)
    2 操作datagridview,然后一段时间后改变或者填充dtagridview
    3 datagridview本身的一些效果,比如旋转的延时等待,或者其他
    不用异步肯定会出现死机的情况,用了异步可能也要注意一些情况

    一个简单的例子:
    一个showdialog窗体里有个一个datagridview,我用异步读取数据,但是没读完,我关了窗体,这时候,数据读完了,要执行
    datagridview.source=??
    这个时候,会出错,可能不是"在创建窗口句柄之前,不能在控件上调用 Invoke 或 BeginInvoke。"这个错误,而是"资源已经释放之类的",那咱们看看下面的几个方法。
    1 this.components 这个属性

     /// <summary>
            /// Required designer variable.
            /// </summary>
            private System.ComponentModel.IContainer components = null;

    每一个Designer.cs里都有一个这个东西,IContainer接口相当于是一个容器,一个页面全部的东西都会放在里面,你拖一个button或者label都会放在里面,笔者觉得,这个其实就是wpf的一个容器的概念,你可以从root寻找到每一个控件,而IContainer也可以找到你想要的控件,Active激活或者不激活会用到这个。
    窗体释放,components 也会释放

    复制代码
     /// <summary>
            /// Clean up any resources being used.
            /// </summary>
            /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
            protected override void Dispose(bool disposing)
            {
                if (disposing && (components != null))
                {
                    components.Dispose();
                }
                base.Dispose(disposing);
            }
    复制代码

    这个方法会释放,所以可以当做判断窗体是否释放的一个依据,但是笔者不推举

    2 this.IsDisposed
    这个是判断是否已经释放了,用这个判断比 components 要好一些,具体的原因是components在窗体关闭后可能没有释放,而this.IsDisposed窗体必然已经释放了,当窗体是MID模式的时候,由于线程或其他原因,窗体的关闭可能不会释放

    3 IsHandleCreated
    句柄是否创建
    当子空间句柄创建了,而它的parent的句柄由于其他原因没有创建或者已经释放了,则也会出现其他问题,所以这个可以通过Parent.IsHandleCereated来盘点父句柄是否存在或者已经创建

    上面几个方法可以组合用,笔者判断的时候差不多用后两个
    现在说说这两个Invoke 和 BeginInvoke
    Control.Invoke:在拥有此控件的线程上先进先出顺序执行委托
    Control.BeginInvoke:在拥有此控件线程上异步执行委托,也就是可能并非顺序执行,这个有点熟悉,貌似说过了

    最后说说解决方法:
    在Invoke(....)之前加上1 this.components==null 2 this.IsDisposed 3 IsHandleCreated 来return 不执行invoke就可以,当然只是我针对自己遇到的解决的,可能并不适合其他的,但是总不会脱离其中

    复制代码
     set
                {
                    if (IsDisposed ||!this.Parent.IsHandleCreated) return;
    
                    this.Invoke((System.Action)delegate()
                    {
                      
                    });
    
                }
    复制代码

    这是我的判断

  • 相关阅读:
    atitit.TokenService v3 qb1 token服务模块的设计 新特性.docx
    Atitit attilax在自然语言处理领域的成果
    Atitit 图像清晰度 模糊度 检测 识别 评价算法 原理
    Atitit (Sketch Filter)素描滤镜的实现  图像处理  attilax总结
    atitit。企业的价值观 员工第一 vs 客户第一.docx
    Atitit 实现java的linq 以及与stream api的比较
    Atitit dsl exer v3 qb3 新特性
    Atititi tesseract使用总结
    Atitit 修改密码的功能流程设计 attilax总结
    atitit.TokenService v3 qb1  token服务模块的设计 新特性.docx
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/2726840.html
Copyright © 2011-2022 走看看