这几天做一个vb的小程序,为了实现一些效果想使用多线程,发现vb多线程实在不好用,多进程也就是使用Activex exe还可以。本来都已经使用这个Activex技术做好了,今天突然想到,对于我这个程序来说完全可以使用doevents达到我的效果啊,赶紧查资料,半个小时编码,搞定,哈哈哈。

贴上查的资料

我要实现一个类似Windows复制(移动)文件时的提示窗体,耗时很长,且要求中断后能继续未完成的操作,不知使用DoEvents从长循环中跳出后,程序将从何处开始继续执行,是否是从DoEvents所在的Sub开始?(倔小孩)

事实上仅使用DoEvents,并不意味着从长循环中跳出。DoEvents只是允许用户选择其他按钮而已,不中断循环,不管用户如何操作,都继续执行 DoEvents后面的语句,即使用户按下了中断按钮,你的循环仍然在继续,甚至你关闭了窗体,程序仍然继续在后台运行。正确的中断处理是这样的:
1、建立一个全局或窗体变量bRun。
2、在启动循环前设置bRun为True。
bRun = True
While bRun And (....)
....
DoEvents
Wend
...
3、在中断按钮Click事件中加入代码:
bRun = False
4、在Form_Unload事件中加入代码:
bRun = False
这样一旦用户按下了中断按钮,bRun = False,循环的条件就不满足了,所以退出循环,执行后续语句。你也可以采用下面的方式:
bRun = True
While ....
If Not bRun Then
Exit Sub
End If
....
DoEvents
Wend
...

郭勇的意见:
《解析 事件,Doevents,闲置循环和控时循环中的难点问题》
Visualbasic6.0 代码
copyright guoyong in cqums(2004-2-26)
关键问题归于doevents 函数
DoEvents函数的功能是:转让控制权,以便让操作系统处理其它的事件。
问:为什么要用doevents?
A.在需要用某一循环处理相当耗时或者很快速的代码时,就需要用到它,以便用户能在起处理过程中能做其他事情,即程序能被控制,而不是无响应状态
B.vb6.0中多线程vb代码极度不稳定,而且无法调试,所以vb中的多线程用的很少(注:是指vb的代码在多线程中运行时不稳定)
C.timer控件可以起到后台运行作用,但其是通过事件控制,一是不稳定,二是速度太慢,如果想用其处理高速又耗系统的代码更本不能达到预期的效果

下面将其某些用法和难点简介如下:

(注: '** 后面的代码表示如果在该处用了这个语句
以下代码中用到了一些api函数,请用vb附带的api浏览器查阅)

一. 基本用法:
1.窗体启动时如果要处理的事务太多或者用sleep函数暂停,造成其很久都不能出现时怎么办?
例如代码:
Private Sub Form_Load()
Show
'**DoEvents
Sleep 5000
End Sub
通常容易想到在sleep前加个show,但还是不能达到预想的效果,窗体虽然出来了,但好象只达到了一半,如果加上第3句,将看到效果大不相同

2.如果有个很耗时的循环导致程序不响应,怎么办?
例如:
Dim L As Long
For L = 1 To 1000000
'** DoEvents
Next L
如果无'**,在循环过程中程序无法处理事件,对于用户来说是不响应,无法控制的
3.想在循环中看到处理过程?
同样:
Dim L As Long
For L = 1 To 10000
'** DoEvents
Text1.Text=Cstr(l)
Next L
无'** 时将无法看到text1中的变化,而只在循环结束时看到最后结果
4.怎样中止循环?
如果有:
Private Sub Command3_Click()
Dim L As Long
Do
L = L + 1
Debug.Print L
DoEvents
Loop
End Sub
会发现当关闭窗口后,debug中的数据仍然在变化,说明并没结束
需要如下:
Dim IsExit As Boolean
Private Sub Command1_Click()
Dim L As Long
IsExit = False
Do While DoEvents
If IsExit = True Then Exit Do
L = L + 1
Loop

End Sub

Private Sub Command2_Click()''或者在form_unload模块中等等
IsExit = True
End Sub
其中 isexit是全局变量
<>有些人喜欢用end语句来结束程序,小程序固然可以,但当太大,或者调用了某些特殊的api函数后可能导致预想不到的错误,如果装载了许多东西在程序结束时不处理将卸载很慢,而且这种做法也极不符合正规软件的要求...总之end语句毛病很多,此不详谈,建议少使用甚至不使用

二. 其基本用法大概就这些,现在解析其中的一些[难点]

1.为什么还是不能结束?
代码如下:
Dim IsExit As Boolean
Private Sub Command1_Click()
Dim L As Long
IsExit = False
Do
If IsExit = True Then Exit Do '句0
DoEvents '** 句1
Text1.Text = CStr(L) '** 句2
L = L + 1
Loop
End Sub

Private Sub Form_Load()
Static N As Long
N = N + 1
MsgBox N
End Sub

Private Sub Form_Unload(Cancel As Integer)
IsExit = True
End Sub

运行结果:启动时msg显示1,点击command1,text1在变化
此时再点form右上角的小差(关闭窗体),发现vb运行控制上的按扭并没变化,说明程序还在运行.如果编译成程序后运行,按下ctrl+del+alt也可发现它还没结束.
通过读代码,并没发现错误,怎么回事?

关键在于 句2 访问了控件的属性
代码运行路径:当在doevents 时,程序释放控制权,可以接收事件消息,form-unload事件只能从此处产生,假设此时关闭form ,unload事件发生,即doevents后就运行unload代码,得到isexit=t,并且form卸载,代码返回到doevents 之后,运行 句2.注意现在form 已经卸载了,text1从哪里来呢?
于是form重新装载,代码跳到form_load模块运行,所以在关闭窗体后可以看到msg 显示2,此模块运行完后再继续句2后面的代码,当下次循环遇到 句0时退出循环
另:既然退出了循环,怎么还不能结束?
vb程序规定(其实其他的windows语言一样):窗体卸载时并不是立即卸载其模块代码,而只先卸载窗体中的控件和一些属性值,程序中最后一个窗体卸载时才完全卸载.
在这个单窗体程序中,form卸载时因为循环的控制无法卸载代码,失去了卸载代码的机会,导致再也不能卸载(因为没卸载代码,所以运行的 句2 是并不会出错)
另:既然再次运行了form_load代码,怎么看不见窗体?
因为程序启动时窗体的到显示的消息,而只运行此模块并没有(如果在msgbox n语句前加上show,就可以看到它了)
如何解决?
通过以上分析,应该很简单,把句1 和句2调换一下就可以了,关键:
<仔细分析代码是如何运行的,避免在form已经卸载了情况下访问控件>

2.用了doevents速度太慢了怎么办?
doevents的代价是速度变慢,但要程序响应又不得不用
其实doevents语句允许任何应用程序执行相关事件,而不仅仅是你自己的程序,所以变得很慢.
可以让它响应本程序事件动作,需要用到api函数GetInputState
例如用: If GetInputState() Then DoEvents '来代替doevents可使循环运行更快

3.既要同时响应事件又要控件不变化,怎么办?
例如在一个长的循环中向listview控件中添加记录,无doevents时程序无响应,但有它时控件又闪的厉害
解决办法:a.不一定每次循环都doevents,可以在适当时间时才用,至少没那么闪
b.应用api函数 ValidateRect 功能是使指定的矩型区域生效,通知Windows不对指定的区域进行重画另:InvalidateRect 功能相反,同时需要用到函数 GetClientRect 取得指定对象的矩形区域应用*rect函数指定listview的矩形区不重画,即可避免闪烁(但还是要注意恢复重画,否则看不见了真实效果)

4.控时循环和变速齿轮
请看下面的代码:
Option Explicit
Private Declare Function timeGetTime Lib "winmm.dll" () As Long
Dim IsExit As Boolean
Private Sub Command1_Click()
Dim L As Long
Dim Kt As Long
IsExit = False
Do
Kt = timeGetTime()
'do something
L = L + 1
Text1.Text = L
'DoEvents '句 1
While timeGetTime - Kt < 50 '句 2
'While Abs(timeGetTime - Kt) < 50 '句 3
'While Abs(timeGetTime - Kt) And (Not IsExit) < 50 '句 4

DoEvents '句 5
Wend
'DoEvents '句 6
If IsExit Then Exit Do
Loop
End Sub

Private Sub Form_Unload(Cancel As Integer)
IsExit = True
End Sub
其中可用的代码(除去加"'" 号的代码)就是通常的控时循环代码
运行代码并不会出现错误,但在循环过程,请开启变速齿轮看看
当关闭齿轮时,将发现text1.text停止了,别慌,等一段时间它又会继续(这要看你设定的时间,这里是50毫秒,如果设定的太长text1.text将半天都没变化,这是怎么回事?
变速齿轮在启动时将hook.dll映射到你的程序地址运行,更改了timegettime()函数获取的时间
如果在句2和句3间插入debug.print timegettime,timegettime-kt 将发现,在关闭齿轮的瞬间后者变成了负值,timegettime变小了,所以才造成需要等很久
如果是编写游戏,而用户开了齿轮,那可就惨了

解决方案:
a.用句3代替句2,这个方法最简便,虽然不符实,但不会出问题,建议使用
b.不要句5,换用句6(这样就能达到效果吗?) 因为齿轮还是从doevents语句运行时才能插的进来,所以只要kt=timegettime 和 timegettime之间没有doevents就不会出错
ab.两种方法都有些小问题,但无大碍,有兴趣者请自己分析

5.程序怎么"死了"?
这只是一些人编写时没注意到的小问题,提醒一下:
同样用上面的代码,如果设定的时间太短,以至在代码运行到句2时已经超时了,句5将不能运行了,当然程序就死了哦,以防万一,加上句1,所以此时也只能用a方案来解决齿轮的问题了
有必要用句4代替句3 吗? 除非你设定的时间太长,人家想关闭你的程序要等上好半天
(是COPY文件,觉的不错,就收藏起来了,希望看到的对你有用)

转载于:https://www.cnblogs.com/xioxu/archive/2007/10/17/928145.html

VB的doevents,制造多线程的效果相关推荐

  1. Vb.Net实现图片合并(相框效果)

    Vb.Net实现图片合并(相框效果) Imports System.Drawing Imports System.Drawing.Imaging Imports System.Drawing.Draw ...

  2. vb调用蜂鸣器制造音阶

    vb调用蜂鸣器制造音阶 Private Declare Function Beep Lib "kernel32" (ByVal dwFreq As Long, ByVal dwDu ...

  3. VB中DoEvents的注意事项

    对与再大循环里 加入   DoEvents却是可以使应用程序响应其他程序,但是 DoEvents也会很大程度上影响循环的速度,所以一般情况我这样用 If GetInputState Then DoEv ...

  4. VB实现移动鼠标产生粒子效果

    VB实现粒子效果 Private Declare Function SetPixel Lib "gdi32" (ByVal hdc As Long, ByVal x As Long ...

  5. 【有利可图网】设计教程:制造裂纹人像效果

    今天分享一个制作裂纹人像效果的教程,操作起来比较简单,直接找裂纹素材叠加到想要的区域,可以适当变形处理,然后用蒙版控制好范围:后期再调整一下颜色.明暗.细节等,得到想要的效果.

  6. vb中DoEvents是什么意思

    Private Sub Command2_Click() Picture1.AutoSize = True Do xx = Rnd * Picture2.Width yy = Rnd * Pictur ...

  7. 通过PR 制造拍照效果(快门角度)

    文章目录 1.制作快门角度 1.制作四个角 2.制作中间的描边圆圈 2.相机框的制作 1.相机框边和中间的去除 3.手机相机框的模糊 1.对背景和视频进行遮盖 2.使用颜色键 3.调整模糊度 4.快门 ...

  8. Doevents函数详解

    Doevents函数是一个很好用的函数,但很多人对它的用法不清楚或有误解.由于我在网上查到一篇关于此函数的用法,并添加了一些内容,不敢独享,特此献出.     其中有一个"控时循环和变速齿轮 ...

  9. DoEvents的用法

    注:摘自互联网 VB DoEvents用法 VB6.0 Windows98 我要实现一个类似Windows复制(移动)文件时的提示窗体,耗时很长,且要求中断后能继续未完成的操作,不知使用DoEvent ...

最新文章

  1. 荣耀总裁赵明:AI 是核心战略,全球前五的目标不会变
  2. linux 安装rpm no key,yum 安装报 关于Public key for *.rpm is not installed 的解决方法
  3. github使用的一点记录。
  4. STM32F1笔记(十三)SPI
  5. stl标准模板库_C ++标准模板库(STL)中的array :: fill()
  6. 【IoT平台技术对接分享】如何上传正确的消息推送证书
  7. java使用smtp发送邮件问题
  8. 持续集成部署Jenkins工作笔记0004---Subversion环境要求
  9. 【数据结构笔记06】队列及其顺序存储、链式存储
  10. 【讲座预告】Processing Learner Texts: from Annotation to ...
  11. [Android1.6]动态添加View的问题
  12. Machine Learning Books List
  13. c语言电子时钟课程设计报告,模拟电子时钟c语言课程设计设计报告.doc
  14. 创新驱动 | 悬镜安全持续入选《CCSIP 2021中国网络安全产业全景图》
  15. womic网络错误_Womic为什么无法用usb连接
  16. C++ ODB学习(阿里云服务器测试)
  17. Mount is denied because the NTFS volume is already exclusively opened.
  18. 每日一书:《性能测试从零开始loadrunner入门与提升》PDF高清版
  19. 读书寄语:所有的遇见都是有原因的,并不只是偶然
  20. babel : 无法加载文件 C:\Users\Lenovo\AppData\Roaming\npm\babel.ps1 ,因为在此系统上禁止运行脚本。

热门文章

  1. 高中会考access数据库_Access操作会考复习.doc
  2. python中注释的作用_Python函数添加注释的好处
  3. fwoa中做excel导入时page理解
  4. Linux命令速查手册
  5. 喝杯咖啡,就买不到NIPS门票了!11分38秒售罄
  6. AutoX创始人肖健雄来信:无人车量产的4大技术储备
  7. 一个八卦的AI,嗅到了你和TA之间基情满满
  8. CES上那些卖萌耍酷的家用机器人究竟怎么样?还是不太懂人话
  9. 08Vue.js快速入门-Vue综合实战项目
  10. Transaction rolled back because it has rollback-only