事情是这么来的,我开发的一个程序报了一个错误 “在创建窗口句柄之前,不能在控件上调用 Invoke 或 BeginInvoke错误”。

然后我在网上查资料,发现一个有意思的问题,文章出处为“在创建窗口句柄之前,不能在控件上调用 Invoke 或 BeginInvoke”错误。

问题

程序是如下这样的。

Form1有Button1、Button2和Button3两个按钮,Button2是动态的new Form2窗体,Form2中注册了Form1中的事件.

Button1的作用是关闭所有new出来的Form2窗体,并且把其资源释放掉(Dispose()).

Button3是让Form2中注册Form1了的事件都发生。

操作:

先点Button2  new出几个Form2的窗体,然后点击Button1释放掉所有的资源,然后再单击Button2 new出几个Form2的窗体,再单击Button3问题就出现了。老是提示"在创建窗口句柄之前,不能在控件上调用 Invoke 或 BeginInvoke"。

作者给出的解析

“在Window窗体程序开发的时候,如果使用多线程编程,在子线程中访问主线程窗体内的控件,就需要使用控件的Control.Invoke方法或者BeginInvoke方法。但是有时候因为Window执行速度太快,尤其是你写代码的时候在InitializeComponent();完成之前起了一个线程去执行某些操作,涉及到窗体控件的,当你在调用Control.Invoke的时候,就可能出现 “在创建窗口句柄之前不能在控件上调用 Invoke 或 BeginInvoke”错误。

这个解释我感觉十分有道理。

给出的解决方法

解决的办法就是让线程等待,直到窗口句柄创建完毕:
//防止在窗口句柄初始化之前就走到下面的代码
while (!this.IsHandleCreated)
{
    ;
}
this.BeginInvoke(new ProListIndexChangedDelegate(GetProLyric));

//根据不同情况也可以:
if (this.IsHandleCreated)
BeginInvoke(new ProListIndexChangedDelegate(GetProLyric));

其它人(钻葛格)给的解决方法:

一个更巧妙的方法,只要在BeginInvoke方法的调用语句前再加一句:IntPtr i = this.Handle;就OK了,这比死循环配合this.IsHandleCreated的判断方法更简洁,因为this.Handle这个属性本身就对应一个方法,取不到句柄,程序就不会向下进行。

如果以上方式时,IntPtr IsHandleCreated = this.Handle;报错:“从不是创建他的线程访问”。则可把this换成你想提取的句柄所在的线程中的窗体类(或其中任一控件)的实例名。

本人也就是通过该方法最终解决问题的。也很有可能是作者给出的解释的那种原因。

结果

作者的解决的结果

再次新建窗体的窗口句柄在Show()之后都通过IsHandleCreated属性检测过了,再调用Invoke()之前都创建了,还是会出错。那问题出在哪里呢?一开始还以为单击Button1没有真正的释放资源,然后我就强制GC了,然后检测不到以前的窗体了,但是还是不行,还是有问题。

然后就想到了“事件”上面来了。是不是事件的原因呀?以前创建的窗体没有注销该事件,把之前所有的窗体都注销该事件,问题就解决了......

有留言认为作者的意思是:根本不是没创建的原因,而是没有清空事件。

我觉得确实应该是访问了没有创建的UI资源造成的!作者的解决方法是对的,但是说法是错的。
也就是作者在Button1中释放(Close)了Form2了。而却没有取消Form2中所订阅的Form1的事件。
此时当点击了button3的话,将激发Form1中事件的委托链,而已经释放掉的Form2对象的事件的响应,由于找到不到该对象资源了,造成了老是提示"在创建窗口句柄之前,不能在控件上调用 Invoke 或 BeginInvoke"。
解决办法缺失如作者所说,去除已经被释放对象的订阅的事件即可。

C#中有关资源、BeginInvoke, Invoke和事件的事情的更多相关文章

  1. MVVM设计模式和WPF中的实现(四)事件绑定

    MVVM设计模式和在WPF中的实现(四) 事件绑定 系列目录: MVVM模式解析和在WPF中的实现(一)MVVM模式简介 MVVM模式解析和在WPF中的实现(二)数据绑定 MVVM模式解析和在WPF中 ...

  2. Delphi中关于资源释放(Free,Relealse,FreeAndNil)

    根据日常编程经验,得出一些Delphi中关于资源释放的体会. 假如有对象Obj为TObject类型: 1) Obj.Free直接释放资源后,调用OnDestroy事件,但是没有将Obj指针值置为Nil ...

  3. 【Android 界面效果30】Android中ImageSwitcher结合Gallery展示SD卡中的资源图片

    本文主要是写关于ImageSwitcher结合Gallery组件如何展示SDCard中的资源图片,相信大家都看过API Demo 中也有关于这个例子的,但API Demo 中的例子是展示工程中Draw ...

  4. Oracle中常见的33个等待事件小结

    在Oracle 10g中的等待事件有872个,11g中等待事件1116个. 我们可以通过v$event_name 视图来查看等待事件的相关信息     一. 等待事件的相关知识 1.1 等待事件主要可 ...

  5. MFC的dll中控制资源问题

    有程序EXE和DLL,其中DLL中有1个函数用来显示对话框,被EXE调用.当EXE和DLL都为Release或Debug时,没有任何问题,但EXE为Release.DLL为Debug时,就会出错.该D ...

  6. MVVM设计模式和在WPF中的实现(四) 事件绑定

    系列目录: MVVM模式解析和在WPF中的实现(一)MVVM模式简介 MVVM模式解析和在WPF中的实现(二)数据绑定 MVVM模式解析和在WPF中的实现(三)命令绑定 MVVM模式解析和在WPF中的 ...

  7. Android开发---如何操作资源目录中的资源文件4 ---访问xml的配置资源文件的内容

    Android开发---如何操作资源目录中的资源文件4 XML,位于res/xml/,这些静态的XML文件用于保存程序的数据和结构. XmlPullParser可以用于解释xml文件 效果图: 描述: ...

  8. Android开发---如何操作资源目录中的资源文件

    效果图: 1.activity_main.xml <?xml version="1.0" encoding="utf-8"?> <Linear ...

  9. 通过源码浅析Java中的资源加载

    前提 最近在做一个基础组件项目刚好需要用到JDK中的资源加载,这里说到的资源包括类文件和其他静态资源,刚好需要重新补充一下类加载器和资源加载的相关知识,整理成一篇文章. 理解类的工作原理 这一节主要分 ...

随机推荐

  1. [ python ] 格式化输出、字符集、and/or/not 逻辑判断

    格式化输出 %: 占位符 s: 字符串 d: 数字 %%: 表示一个%, 第一个%是用来转义 实例: name = input('姓名:') age = int(input('年龄:')) print ...

  2. CSU 1240 低调,低调。

    原题链接:http://acm.csu.edu.cn/OnlineJudge/problem.php?id=1240 这道题已经做了很久了,加入给足够大的内存,谁都会做. 在一个数列中找一个只出现一次 ...

  3. serial minicom

    这是一篇讲述串口很好的入门教程: http://users.ece.utexas.edu/~valvano/Volume1/E-Book/C11_SerialInterface.htm 如何显示串口数 ...

  4. beego与websocker的集成

    上周刚好遇到这个问题. 周末在家里按网上的方案测试了一下. 希望下周进展顺利~~ URL: http://blog.csdn.net/u012210379/article/details/729120 ...

  5. Java Hibernate和.Net EntityFramework 如何在提交事务之前 就拿到需要新增实体的Id

    在Hibernate中很容易做到这一点,因为hibernate在事务commit之前  还有一个save方法,这个save方法就可以持久化并且拿到Id. 但是EF并不可以呀,EF是将对象标记为新增状态 ...

  6. 第六章:加载或保存JSON数据

    加载或保存JSON数据 Knockout可以实现很复杂的客户端交互,但是几乎所有的web应用程序都要和服务器端交换数据(至少为了本地存储需要序列化数据),交换数据最方便的就是使用JSON格式 – 大多 ...

  7. 久邦数码(3G门户)面试

    久邦数码(3G门户)面试 1.数组和链表的区别(为什么数组带有索引) 2.数据库(手写选出一个公司年龄最大的100个员工) 3.一百个数查找一个数 利用二分查找一个数在最差的情况下至少比较多少次 4. ...

  8. ref:浅谈XXE漏洞攻击与防御

    ref:https://thief.one/2017/06/20/1/ 浅谈XXE漏洞攻击与防御 发表于 2017-06-20   |   分类于 web安全  |   热度 3189 ℃ 你会挽着我 ...

  9. Linux (x86) Exploit 开发系列教程之六(绕过ASLR - 第一部分)

    转:https://bbs.pediy.com/thread-217390.htm 前提条件: 经典的基于堆栈的缓冲区溢出 虚拟机安装:Ubuntu 12.04(x86) 在以前的帖子中,我们看到了攻 ...

  10. 20169211《Linux内核原理与分析》第三周作业

    假期中抽时间学习了一下linux内核的启动过程,在此做一下学习总结. Linux启动过程描述: 1.启动BootLoader 2.Linux系统的初始化 3.Linux的应用程序的初始化 通用寄存器的 ...