【Winform】关于Application.DoEvents()的理解
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()的理解相关推荐
- C# Winform中慎用Application.DoEvents
private void Add(){for (int i = 0; i < 100; i++){Button button = new Button();button.Width = 300; ...
- C#Application.DoEvents();的作用。
Visual Studio里的摘要:处理当前在消息队列中的所有 Windows 消息. 交出CPU控制权,让系统可以处理队列中的所有Windows消息 比如在大运算量循环内,加Application. ...
- WPF 延时操作实现 --- Application.DoEvents()
WPF 延时操作实现 - Application.DoEvents() 如果是在Winform中,我们可以这样实现 sleep延时方法: System.Threading.Thread.Sleep(1 ...
- C# Application.DoEvents() 处理队列消息,防界面假死。
该方法可以处理当前队列的消息,比如一个for循环 5000次 向TextBox中追加文本,那肯定会假死一会儿的. 此时便可使用Application.DoEvents()来处理队列的信息. 简单说下使 ...
- c# Application.DoEvents
public static void Delay(int ms){int start = System.Environment.TickCount;while (System.Environment. ...
- Application.DoEvents()的使用
最近做了一个个人数字图书馆管理系统,因为牵扯到电脑文件的扫描,想做一个实时显示当前扫面文件的功能,就类似于360文件扫描时的效果,本来打算用多线程来实现,但是方法太多没有实现,后来在程序中进行控制,由 ...
- Application.DoEvents
记得第一次使用Application.DoEvents()是为了在加载大量数据时能够有一个数据加载的提示,不至于系统出现假死的现象,当时也没有深入的去研究他的原理是怎样的,结果在很多地方都用上了App ...
- Application.DoEvents可能不是线程安全的
2019独角兽企业重金招聘Python工程师标准>>> 如果在UI的消息处理函数中进行较大量的计算或对界面进行操作,占用较长时间时可以在中间调用Application.DoEvent ...
- Application.DoEvents();
一直做的是WEB开发,就没有用到过Application.DoEvents();最近搞手机客户端开发,看到代码里面有这个方法不知道是干什么的.搜了哈.分享分享 Application.DoEvents ...
- 慎用Application.DoEvents( )
如果在UI的消息处理函数中进行较大量的计算或对界面进行操作,占用较长时间时可以在中间调用Application.DoEvents来响应用户操作,但不建议这样做,替代的方法就是在后台线程中进行这些操作, ...
最新文章
- Go modules基础精进,六大核心概念全解析(上)
- 编译自己的emacs
- 洛谷2051 [AHOI2009]中国象棋
- VWware安装ubuntu设置静态IP
- 2019ICPC(南昌) - Hello 2019(动态规划+线段树维护矩阵)
- errno的基本用法
- μC/OS-Ⅱ 操作系统内核知识
- 前端学习(2017)vue之电商管理系统电商系统实现表单的预先认证
- 面试官:你给我画一下秒杀系统的架构图!
- shell中返回值是1为真还是假_肝!Shell 脚本编程最佳实践
- oracle的服務監聽器,Oracle监听器和服务名的配置
- linux硬盘类型怎么选,如何选择linux系统安装类型
- 关于es cpu安装黑苹果,并实现变频
- 项目实训(十三)安装pun,pun的基础使用和概念
- kubectl rollout restart重启pod
- PDJCAD皮带机设计软件
- Must call super constructor in derived class before accessing 'this' or returning from derived const
- 李俊计算机哈佛大学,李俊-中国科学院大学-UCAS
- 用长微博工具发布长微博
- 【Solr】之使用springboot完成对【京东搜索商品】案例的实现
热门文章
- 软件测试面试题(全)
- 计算机没有安装鼠标和键盘驱动,鼠标不能用如何安装驱动程序-使用键盘安装鼠标驱动的方法 - 河东软件园...
- Qt-QtDesigner插件编写
- 高斯过程分类和高斯过程回归_高斯过程回归建模入门
- shp文件根据属性导出若干单独shp
- 超高频RFID通道门禁 仓储物流收发货系统应用
- 【Linux】ubuntu18.04 安装英伟达显卡驱动
- mysql英文版怎么调中文_navicat for mysql怎么设置中文
- android 模板引擎,template.js模板引擎
- sklearn实现随机森林回归预测