在创建窗口句柄之前,不能在控件上调用 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 和 BeginInvokeControl.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()
                {

                });

            }
 
时间: 2024-10-17 21:19:53

在创建窗口句柄之前,不能在控件上调用 Invoke 或 BeginInvoke的相关文章

C# 多线程修改控件时,提示在创建窗口句柄之前,不能在控件上调用 Invoke 或 BeginInvoke

一般在多线程调用UI控件时,涉及到跨线程修改UI,需要使用委托,比如如下: this.Invoke((MethodInvoker)delegate { btnRefresh.Enabled = true; }); 但是假如在多线程操作还没完成的时候,我就提前关闭窗体,则会引发InvalidOperationException,提示 “在创建窗口句柄之前,不能在控件上调用 Invoke 或 BeginInvoke” ,并且如果没有捕获到,则可能导致程序崩溃,直接关闭. 百度之后,发现需要判断控件的

在创建窗口句柄之前,不能在控件上调用 Invoke 或 BeginInvoke。

public partial class UCInfo : UserControl { public UCInfo() { InitializeComponent(); } ManualResetEvent neverSetEvt = new ManualResetEvent(false); delegate void InvokeDelegate(); public void SetInfo(string info) { lblInfo.Invoke(new InvokeDelegate(()

C# 在创建窗口句柄之前,不能在控件上调用 Invoke 或 BeginInvoke [问题点数:40分

注意:  this.DateTimeRun = true;            new Thread(jishi_kernel).Start(); 线程的启动,不能放在    public Form1()  构造函数中,因为窗口的控件还没有初始化完成.若线程调用窗口控件,就会报错. 应该放在这个函数里面  private void Form1_Load(object sender, EventArgs e)

C# 在创建窗口句柄之前,不能在控件上调用 Invoke 或 BeginInvoke

http://www.cnblogs.com/fish124423/archive/2012/10/16/2726543.html 在Invoke(....)之前加上1 this.components==null 2 this.IsDisposed 3 IsHandleCreated 来return 不执行invoke就可以,当然只是我针对自己遇到的解决的,可能并不适合其他的,但是总不会脱离其中 if (IsDisposed ||!this.Parent.IsHandleCreated) ret

在创建窗口句柄之前,不能在控件上调用 Invoke 或 BeginInvoke

在用Control. BeginInvoke 方法 更新UI时,需要验证两个前提: 1,Control==null 否则会引发null引用,比较明显的错误 2,DataGridView.IsHandleCreated==true 否则会引发"在创建窗口句柄之前,不能在控件上调用 Invoke 或 BeginInvoke" 可能发生在控件被销毁时,更新UI的线程调用了BeginInvoke

.net 在创建窗口句柄之前,不能在控件上调用 Invoke 或 BeginInvoke。

窗体句柄的创建 窗口创建时,窗口并没有创建句柄,只有Application.Run(form)或者form.Show()之后才有句柄,即窗口只有显示或者启动消息循环后才有句柄!如果创建form之后,主线程中调用form.Handler,如果句柄尚未创建,引用该属性将强制创建句柄,对习哦他能够内的逻辑将产生致命的影响. IsHandlerCreated属性 通过IsHandlerCreated判断句柄是否创建成功,进而考虑是否使用委托方法跨线程操作.常规用法如下: if(this.Ishandle

对话框上动态控件的创建、在Picture Control控件上显示图片

1  MFC对话框之上的动态控件的创建 对话框上的控件是MFC类的一个具体对象. 当在对话框之上使用静态控件时,可以根据类向导来为每个控件添加消息.响应函数以及变量. 当需要在对话框中动态的创建某个控件时,就需要手动来代替类向导为动态控件添加消息.响应函数及变量. 动态创建控件时,可按照以下步骤进行: (1) 明确控件所属于的类 每一个控件都对应着一个类(例如按钮Button所属于的类为CButton). 如,在程序中我们需要用CButton类创建一个具体的按钮对象,并用函数指示它在对话框之上的

创建UPC/EAN/JAN 条形码控件UPC/EAN/JAN Fontware

UPC/EAN/JAN Fontware条形码控件使你的Windows/Linux/UNIX/Mac应用程序创建UPC/EAN/JAN 条码变得极其简单,而且还提供了TrueType, PostScript Type 1, PostScript Type 3 and OpenType 字体,支持UPC-A,UPC-E, EAN13, EAN8, JAN13和JAN8,可以完全整合到你的Crystal Reports, Word, Excel, Access, Visual Basic, Visu

Delphi 查找标题已知的窗口句柄,遍历窗口控件句柄(转)

Delphi 查找标题已知的窗口句柄,遍历窗口控件句柄(转) 用我的方法来控制其他程序窗体上的窗口控件,必须先了解什么是 回调函数.我的理解是这样的: 回 调函数写出来不是自己的程序去调用的,反而是让其他的东西去调用,比如windows操作系统,比如其他的程序等等之类的.但是什么时候被调用却不知道 了.回调函数一般是按照调用者的要求定义好参数和返回值的类型,你向调用者提供你的回调函数的入口地址,然后调用者有什么事件发生的时候就可以随时按照你 提供的地址调用这个函数通知你,并按照预先规定好的形式传