SKY外语计算机学习

标题: vb实现多线程 [打印本页]

作者: SKY定格    时间: 2014-4-11 10:17
标题: vb实现多线程
vb 实现多线程2010-08-03 13:46很多人对VB多线程的评价就是
不稳定,不安全
其实这是一种完全不正确的评论
VB程序对多线程的支持还是非常让人惊喜的
只不过多线程无法在IDE中进行调试而已
而所谓的VB控件多数不是线程安全的
也没有明确依据
因为事实证明VB大部分控件可以再多线程操作下进行的!
网上流传的大部分都是毫无实质性意义的文章
要不说一大堆概念毫无解决方案
直接进入实际教程:
1.相关API
CreateThread(创建一个线程)
声明:
Public Declare Function CreateThread Lib "kernel32" _
(lpThreadAttributes As Any, ByVal dwStackSize As Long, ByVal lpStartAddress As Long, _
ByVal lpParameter As Long, ByVal dwCreationFlags As Long, lpThreadId As Long) As Long
参数说明:
lpThreadAttributes:对于我们的使用基本没什么太大的意义,说了也是废话,直接设定成Null即可,详情可以去MSDN查一下
dwStackSize:堆栈的大小,如果对此不了解,直接设定为0,系统即自动调节
lpStartAddress:线程函数指针,恩恩恩,使用AddressOf即可获得函数的指针了......
lpParameter:为线程函数传递的参数,请注意,别乱传,尽量0传进去
dwCreationFlags:线程的参数标志,可以创建挂起的线程或者立即激活线程,默认设定为0即可立即激活线程了
lpThreadId:线程的ID
返回值:线程的句柄
以上核心的API声明完毕,只有一个,简单吧
其实线程的难处还在后面,废话不多说,讲一下创建线程吧
首先创建一个窗体,名称:Form1.一个模块,名称xywhThread
窗体中建立一个标签
模块内声明延时函数的API(如果不是多线程就不要用这个了,因为很卡,可以使用xywhAPI里面的延时函数)
Public Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
然后在模块内建立一个过程,名称:xywhXC1
过程的代码可以是这样:
Sub xywhXC1()
Dim i as long       '之前代码忘记了声明这个,在线城中是不被允许的。
Dim TempStr As String
     For i = 1 To 10000
         TempStr = CStr(i)
         Form1.Label1.Caption = TempStr
         Sleep 20
     Next
End Sub
在窗体的load事件中
可以加入这样一个函数指令:
asd = CreateThread(Null, 0, AddressOf xywhThread.xywhXC1, VarPtr(0), 0, threadid1)
按照我上面的API说明解读,不难明白这是一个创建线程的语句
请注意,用VB玩线程要有很多的注意,最主要的是不能调试执行
必须生成EXE然后执行
最好是生成P-Code
上面的程序做好以后
保存,生成EXE
然后执行以下试试看
你就会发现
程序运行后
标签数字不断累加
而且程序一点都不卡
因为是多线程操作的啦
想到在那里应用了吗?
一直有很多垃圾评论VB多么多么不好
效率多么多么低
经过多线程优化过的VB程序
效率其实完全可以和C媲美的!!!
请注意,这是一个非常严重的问题
任何线程所应用到的变量,请注意,只要是线程贴边的任何变量
都要声明!
绝对不能使用隐式声明
多线程虽然已经实现了
但是......
总感觉退出时候的对话框怪怪的
这是为什么呢?
大概比尔大叔没有想到世界上还有一部分执着的VB爱好者竟然能用VB写多线程
所以比尔大叔也抱着侥幸心理的让VB在生成EXE时候的退出代码中
只结束了主线程
怎么证明?很简单
保存工程(这是必须的!!!!!!!)
然后在IDE里面调试执行
然后暂停!
看看窗口,咦,为什么那个啥啥啥标签还在更新
因为IDE只能调试主线程
OK
然后点一下结束
后果很严重,IDE直接挂掉
其实程序退出时候造成的内存无法读取或写入的错误
是由于VB卸载了主线程,但是却不卸载我们创建的线程
因此当我们创建的线程还在继续工作并且访问主线程窗口的标签时
就会出现无法访问的问题
那么怎么能够避免此问题呢?
首先我们吧线程对象的循环数调整为100
然后生成EXE执行看看
标签更新到了100的时候
在进行退出
就不会出现内存无法读写的问题
这足以证明
线程函数 结束的时候,线程也会被结束掉,因此,我们可以设置线程执行退出时就结束掉线程过程
提供了几个API让我们操作进程
首先我们需要获取自己的进程句柄
然后利用API干掉自己,自杀?
我看过一个自身删除的.....
很多人都在说END以后调用CMD。然后ping一个慢点的网站
因为他们用的END,处理比较慢,所以要ping慢点的网站,如果使用结束进程的话
直接ping127.0.0.1既可了......
废话不多说
继续教程
API声明:
Public Declare Function TerminateProcess Lib "kernel32" (ByVal hProcess As Long, ByVal uExitCode As Long) As Long
Public Declare Function GetCurrentProcess Lib "kernel32" () As Long
这个呢......就是活的自身进程句柄的函数咯,他没有任何参数,直接调用返回的就是自己的句柄了
结束进程的API第一个参数是进程句柄,第二个参数就是退出码
第二个直接设定为0既可,第一个就是获取自身句柄的咯......
代码如下:
TerminateProcess GetCurrentProcess, 0
在窗体的unload中使用上面的结束自身代码
就会发现自己被迅速的结束了
任何对话框都没弹出来
看来VB的退出确实非常不理智......
那么我们换位思考下
既然每一个线程的过程执行完毕后都会自动释放掉
(其实每个线程可以看做一个程序,良好的程序员绝对不会拘谨与进成语线程的定义)
线程可以看做一个单线程的程序,如果没有任何的代码就会自动退出一样
因此我们可以通过一种变通的方式进行现成的安全退出
而不必“学习”所谓的高手的API结束方式
那么怎么变通呢?
首先,多线程的应用都是做些什么呢?
无非就是,循环用以执行高占用率的代码
那么循环执行的话,只要添加一个监视就可以啦!
对!
只需要添加一个监视
在线程内部一般人都会防止过分占据资源而使用Sleep
那么在Sleep之前进行判断是否进行线程循环
如果进行的话
就结束掉处理过程
然后主线程等待1秒或者比线程中的SLEEP延时更长哪怕一毫秒的时间
OK
看看线程是不是非常安全的退出了呢






欢迎光临 SKY外语计算机学习 (http://skywj.com/) Powered by Discuz! X2.5