Winform开发时,偶尔会在一个耗时的处理中用到Application.DoEvents()这个方法,可以让UI线程在当前代码上下文中切换去处理其它Windows消息,从而避免界面的假死。

例如,经常会这么用:

        public static void Delay(int nMilliSeconds){DateTime dt = DateTime.Now;dt = dt.AddMilliseconds(nMilliSeconds);while (dt > DateTime.Now){Application.DoEvents();//转让控制权}return;}

在UI线程中调用这个方法,就可以阻塞当前执行的上下文一段时间,阻止代码继续执行,但同时又不会导致界面假死。效果类似于Thread.Sleep(),但Sleep()是让UI线程直接阻塞,从而停止响应。

这种功能当然用多线程是可以做到的。但这种方式相比多线程的优势就在于代码简洁和无需做线程同步。

从应用的角度来讲,这个方法是一大利器,可以在单线程里实现类似多线程的效果。但是既然如此,为什么微软的官方文档里都没有看到这个推荐使用这个方法呢?猜想这个方法应该有较大的副作用。

随后在CSDN一篇帖子上看到一位大佬讲述了这个方法的历史,以下摘自原帖:

DoEvents 是 vb(4、5、6)的产物,因为那是单线程的。
它的机制是将你的应用中尚未触发的windows消息大乱次序、提前触发。比如说你在鼠标点击某个控件时会去调用过程a,在鼠标在此控件移动时会去调用过程b,同时在timer定时器到时时回去调用过程c,那么你会看到DoEvents 造成了在a尚未结束时反复调用了b、c等等过程,主线程中明明是顺序的代码,调用时一片混乱无法调试。而且往往会导致事件的爆炸性的循环调用(类似于无线递归没有节制),直至系统资源耗尽而崩溃。
正常的主线程异步操作,是可以明确地知道过程在主线程中被调用的先后次序的,可以明白地调试代码(明白地看懂调用堆栈)。主线程都是先调用完a,然后才可能调用b、c,并不是在过程中去拆自己的台。因此如果需要循环触发,那么就使用定时器。
DoEvents是vb那个时代的产物,应该终止与vb6(1998年)的时代。如果你要简单移植vb6的程序,可以用它。如果不是就不要用它。

另外,在应用程序设计中搞“死循环”这是很令人不忍看、不忍“闻”的设计方式。如果你认为主线程经常要重复干一件(逻辑的)事儿,就必须写一个死循环,那么我只能说我们是绝对不用这样的程序员的。
在设计上,除非万不得已实在活不下去了,否则不允许随便写“死循环、阻塞”的代码。
写死循环,是因为有些人只知道刚入门学c等等几十行的简单小计算程序时学到的那种思路,因为那些是“输入-输出”式的简单函数。
如果你学习交互式程序设计,假设有10个独立的(貌似循环)的功能行为,那么凡是交互部分,都必须“断开”,然后每一个片段都必须是事件驱动(包括定时器事件驱动),这样才能组合成为一个完善的应用。难道你要写10个死循环,然后再胡乱地DoEvents调用?这是编程大忌。

把设计中各种事件循环发生,代码上写成许多个死循环,这是没有学过应用程序设计的表现(可能只是从一些数学相关的课程中学了一些简单的函数编程)。一定要从设计思路上学会事件驱动的设计方法,而不是纠结于编程语句。

原贴地址:
Application.DoEvents();多次调用会有什么隐患,望有经验的朋友分享下!

这里所说的导致一些代码的逻辑顺序混乱,这种现象倒没有遇到过。导致效率变低倒是有。这种代码本身就违背了程序设计规范,是过程式编程的遗物,应当尽量避免使用。该用多线程还是得用多线程。

【Winform】关于Application.DoEvents()的理解相关推荐

  1. C# Winform中慎用Application.DoEvents

    private void Add(){for (int i = 0; i < 100; i++){Button button = new Button();button.Width = 300; ...

  2. C#Application.DoEvents();的作用。

    Visual Studio里的摘要:处理当前在消息队列中的所有 Windows 消息. 交出CPU控制权,让系统可以处理队列中的所有Windows消息 比如在大运算量循环内,加Application. ...

  3. WPF 延时操作实现 --- Application.DoEvents()

    WPF 延时操作实现 - Application.DoEvents() 如果是在Winform中,我们可以这样实现 sleep延时方法: System.Threading.Thread.Sleep(1 ...

  4. C# Application.DoEvents() 处理队列消息,防界面假死。

    该方法可以处理当前队列的消息,比如一个for循环 5000次 向TextBox中追加文本,那肯定会假死一会儿的. 此时便可使用Application.DoEvents()来处理队列的信息. 简单说下使 ...

  5. c# Application.DoEvents

    public static void Delay(int ms){int start = System.Environment.TickCount;while (System.Environment. ...

  6. Application.DoEvents()的使用

    最近做了一个个人数字图书馆管理系统,因为牵扯到电脑文件的扫描,想做一个实时显示当前扫面文件的功能,就类似于360文件扫描时的效果,本来打算用多线程来实现,但是方法太多没有实现,后来在程序中进行控制,由 ...

  7. Application.DoEvents

    记得第一次使用Application.DoEvents()是为了在加载大量数据时能够有一个数据加载的提示,不至于系统出现假死的现象,当时也没有深入的去研究他的原理是怎样的,结果在很多地方都用上了App ...

  8. Application.DoEvents可能不是线程安全的

    2019独角兽企业重金招聘Python工程师标准>>> 如果在UI的消息处理函数中进行较大量的计算或对界面进行操作,占用较长时间时可以在中间调用Application.DoEvent ...

  9. Application.DoEvents();

    一直做的是WEB开发,就没有用到过Application.DoEvents();最近搞手机客户端开发,看到代码里面有这个方法不知道是干什么的.搜了哈.分享分享 Application.DoEvents ...

  10. 慎用Application.DoEvents( )

    如果在UI的消息处理函数中进行较大量的计算或对界面进行操作,占用较长时间时可以在中间调用Application.DoEvents来响应用户操作,但不建议这样做,替代的方法就是在后台线程中进行这些操作, ...

最新文章

  1. Go modules基础精进,六大核心概念全解析(上)
  2. 编译自己的emacs
  3. 洛谷2051 [AHOI2009]中国象棋
  4. VWware安装ubuntu设置静态IP
  5. 2019ICPC(南昌) - Hello 2019(动态规划+线段树维护矩阵)
  6. errno的基本用法
  7. μC/OS-Ⅱ 操作系统内核知识
  8. 前端学习(2017)vue之电商管理系统电商系统实现表单的预先认证
  9. 面试官:你给我画一下秒杀系统的架构图!
  10. shell中返回值是1为真还是假_肝!Shell 脚本编程最佳实践
  11. oracle的服務監聽器,Oracle监听器和服务名的配置
  12. linux硬盘类型怎么选,如何选择linux系统安装类型
  13. 关于es cpu安装黑苹果,并实现变频
  14. 项目实训(十三)安装pun,pun的基础使用和概念
  15. kubectl rollout restart重启pod
  16. PDJCAD皮带机设计软件
  17. Must call super constructor in derived class before accessing 'this' or returning from derived const
  18. 李俊计算机哈佛大学,李俊-中国科学院大学-UCAS
  19. 用长微博工具发布长微博
  20. 【Solr】之使用springboot完成对【京东搜索商品】案例的实现

热门文章

  1. 软件测试面试题(全)
  2. 计算机没有安装鼠标和键盘驱动,鼠标不能用如何安装驱动程序-使用键盘安装鼠标驱动的方法 - 河东软件园...
  3. Qt-QtDesigner插件编写
  4. 高斯过程分类和高斯过程回归_高斯过程回归建模入门
  5. shp文件根据属性导出若干单独shp
  6. 超高频RFID通道门禁 仓储物流收发货系统应用
  7. 【Linux】ubuntu18.04 安装英伟达显卡驱动
  8. mysql英文版怎么调中文_navicat for mysql怎么设置中文
  9. android 模板引擎,template.js模板引擎
  10. sklearn实现随机森林回归预测