用VB创建高效的多线程应用程序

上传人:豆浆 文档编号:36340986 上传时间:2018-03-28 格式:PDF 页数:3 大小:354.34KB
返回 下载 相关 举报
用VB创建高效的多线程应用程序_第1页
第1页 / 共3页
用VB创建高效的多线程应用程序_第2页
第2页 / 共3页
用VB创建高效的多线程应用程序_第3页
第3页 / 共3页
亲,该文档总共3页,全部预览完了,如果喜欢就下载吧!
资源描述

《用VB创建高效的多线程应用程序》由会员分享,可在线阅读,更多相关《用VB创建高效的多线程应用程序(3页珍藏版)》请在金锄头文库上搜索。

1、用VB创建高效的多线程应用程序镊撰文 /Ma: :卜eweu r.and编译/卜平关键词v isu alBa sic多线程STAvB本身的机制已经提供了对创建多线程应 用程序 的内在支持,尽管Mic ro soft的官方文献 并 未明确指出这一点。国内介绍创建vB多线程应 用程序的文章大多采用A尸l函数份e a七e丁 hr e ad,但是实际上这种方法并不可取。本文将 向读者展示如何挖掘vB对S丁A的 支持以构 造 多线程的应用程序,如何防止线程 间 的相 互阻塞以执行异 步方法 调用,如何在线程间有效地通讯,以及如何重载S丁 A内建的方法顺序。V is以alBasie6(以及安装了S PZ或

2、SP3的V B S)为创建多线程应用程序提供 了内置的支持。更 明确地说,VB支持在单个进程的 多个线程中运行单线程单元(STA),在一个ST A中运行的任 何代 码 的当 前线程 总是创建该单元 的 线程;它不同干 多线程单元(MTA),MT A允许代码运行在任何线程中。从另一个线程 中调用一个STA要求你在请求 线程中建立一个代理(proxy),并在被调用的STA中建立一个桩 (s tub)。代 理 对象跨越 进 程边界 将 调用列集到 桩,然 后 由桩 调用实际代码。桩与被调用的S TA在同一个线程 中,因此 该被 调用 的STA无法区分 一个调用是 来自线程 内还 是列集自另一 个线程

3、。桩还提 供了内置的顺序,从而 保 证调用按照接收的顺序执 行,只有前一个调 用完成了后一个调 用才允许开始 执行。VB为其线程模型使用STA,因此几乎 所有 困扰 自由线 程的MTA代码 的同步动 作在ST A模型中将被自动处理。我将在这篇文章中为您展示如何挖掘VB对5TA的支持以构造 多线程的应用程序,如何阻止 线程间的相 互阻塞以执 行异步方法调用,如何在线程间有效的通讯,以及如何重载5 T A内建的方法顺序。我将集中介绍如何在Ac ti veXEX E项目中使用这些技术;如果你想在DL L或0CX中创建新线程,步骤将大不相同。创 建多线程应用 程序的快速指南创 建多线程应 用程序需要执

4、行一些步 骤,使用这些简单的 方 法开始:默探靛嘿戏瑞省氢COn一tr乙l erCOrl、 咒群橇俞碗碗一_- 一首先在SubMain中新建一个Controlle r,在Controlle r的Cla ss_Initial主z e中显示frr nMain并且执 行SetfrmMain.Controlle r=Me。新建一 个线程仅仅是对Worke r类调用一次Cre ateobjeet这么简单。V B把Createobjeet调用看成是一个新建 Worker实例的外 部 请求,故而自动新建了一个S T A。如果 你使用New来创建 同一个工程中的 Worker实例,VB将 在同一线程内创 建

5、它。VB对ST A模型的实 现不 支持 真正 的全局变量,这意味着 你无法通过设置全 局标志 来阻止 当 创建工作线程时调用SubMai n 导 致的主Ul重复执行,你也无法从App或其他任何VB对象中获得该信息,因此 你必须使用API调用来确定SubMa in是否在进程中首次被调 用。随V B一起发布的示例代码使用一个隐藏的窗体并通过API函数F indwindow来检测,不过我发现用一个叫Thr eadC heck的类在 本地 原子表中设置一个标志 量 要更简单,也更直观 (见表l)。u 打井一公个扬户勺火幸咖碑琴2 .打开项目属性对话框、E火日项歇燕 薰淤嚣 辣 盛蕊 麟)价洋布需需要额

6、外的 线程吗? ? ?P P Priv atem _ Thr e adC he ek人5NewThr e adChe ek k kP P Prlv a七em _fFa土I Cr e atio nAsBo ole a n n nS S SubMa 上n() ) )D D Dime七1AsCon tr olle r r r1 1 1fm _T hr e adChe ck.F工 r stThen n nI I I上AP P.gta rt Mode二vb SModestandalo n eT hen n nS S Setetl二NewCo ntr OI 工e r r rE E EIS e e em m

7、 m _fFa立ICr e 己tlo n=Tr u e e eE E EndIf f fE E E IS e e eS S Setm _宁hr e adC he ck二Nothinq q qE E EndIf f fE E EndSub翼攀)嚣黔羔滋翼儡Pub l主己 SubVer生fy Crea七1巾戈)工fmfPa主工Cr e d仁工o nThe nlE厂 r.Raise吐2 9, Notfo rpublicc on队 阴pt jon”,_卜扁 翌上竺_ _一一-一-表1T hr 。 。dc h。 。欠类可以检测一个给定的线程是不是工作线程或者说俪不瀚要在该线程上创建UI。然而这样做 有一

8、个 缺点:如果你在1DE中调 试并按下停止按钮,清除本 地原子 表的 代码不会 执 行,重新启动后Thr ead check将会直接返回Fa ls 。,应用程序无法再运行。我在T hreadCheek类中增加了一行Debug.Ass e rt语 句,以便在该问题发生 时告诉你问题 所在。断言语句之前的注释包含了清除该 原 子入日以使你成功的恢复运行的立即窗口代码。就绪、设置、然后一新建线程这一 点使得代码可以同时执行,C OM的同步方法执行 模型很好的满足 了多线程应用程 序的 这 个基本需求。, ,在所有MultiU阴对象的e las sll飞jtiali之 e中调用用, ,不要t戈图跟岭轰

9、 错误。在M a i”中抛出错误会引起崩溃,但是在在, ,c las民一InjLia工 iz e 中可以抛出错误给客户。P P Pub l主己 SubVer生 fyCrea七生巾t ) ) )1 1 1fm _fPa主工Cr e d仁主o nThe n n nE E E厂 r.Raise吐2 9, Notfo rPubliee ons 飞 止mp tjon”E E EndIf f f日日ndSL几b b b码)。在工程中包含提供的这 两个文件以使用该技术模拟异步方法 调用:工叩lementsFl r e乎lme 刃Pri7a匕e汀匕Tme rI DAs乙01王g护ub 工ieSub00七。ng

10、Ta sk丈.保存参数井激活定时器,因此可以立即返回。mT上爪e rI D二SUbAd dT王Ine 厂(Me)Pr 1Vate工上E ndSUbSubC la s_ Te rmlnate()m _ T主犯e r工力Then,某种原因导致定时器尚未激活, 阅此必须请除它。e lea rT主几e rm _丁生几e rI D工fPriVa七eSUbFl r eT 工me r_Go(少.处理传人DOL o呢T部k的数据已ndSub当控制对象 在另一个线程 中创建对象或执行 方法调用时,控制线 程将一直阻塞到该调用返回(见图1)。这导致一个推论:如果一个 项目中的所 有 方法调用都来 自其他 的S T

11、人,那么同时只有一个 线程可以执行代码。切换线程_L下 文需要很高的 代 价;代码在不同线程 中依 序运 行(同 时只有一个线程运行代码) 的性能不 如在同一线程 中运 行的相 同 代码。创建工作线程并工作线程发信号然后从控制线程中提取消息使用 同步 方法 调 用执可以避免这里的死锁。行 其中的 代码是毫无意义的,因此,你需要执行异 步调用的途径。COM没有内置对 异步 方法调用 的支持,这意味着需要一种使每个线 程能够在不阻塞其他线程 的情况下调用 其 自身方 法 的机制,定时器将做到这一点。异步 方法调用 几乎立即 从被 调方法 返回,输入参数 被保存起来,同时启 动一个定 时器来执行回调

12、然 后及时的发 出通知,即 返回。简单起见,在线源代码包含了两个文件,Fireone eTime rs.ba s和Firelime r.e上s(细节见下载的自由代在 隐藏主Ul之前必须关闭任何附加在EXE上的工作线程,如果在主Ul关 闭之前仍然有 运行中的工作线程而且役在通知其结束的话,该进程将被遗漏。vB提 供了两种线程间通 讯的途径:方法 和事件。如 果在Co ntroller中使用方法调用来结束工作线程,Controlle r将被阻寨直至 w0rke r完成其正在执行的方法,原 因是工作 线程在其完成当前方法之前永远不会允许亏to,Now方法执行,这意味着 应用程序死锁。可靠的关闭线程事

13、件比方法调用要稍灵活一些。使用事件,要由Con tro lle r创建一个 Wi七hEventsWo rker,再由Worke r调用Rais eEv e ntstopNow(rDone)来说明是否是关闭的时机了我倾向 于使用 一 个信号的 方法,这 比方法调用 成事件 要直接得多。所有的 线程都运行在同一个进程中,因此它们可以合法的访问其他线程中的内存。很简单,把一个Worker所拥有的长整型值的指针给Con tro ll er,Con tr oll盯线程在该信号指针_L调用线程安全的xnt erloekedxn crementA Px、worker不时的检查该值是否被修改了。只有当Cont

14、r0 11er类保存 了对worker类的引用时才能使用这种信号技术,否则将不能保证该内存不被释放,这样发信号将引起内存冲突并导致程序崩溃 (见表2)。,向其他线程 发信号-一L作类P了主vatem一Not土fyA吕LongPubl ieF,unctio 。对otlfy Poin七e r()入5Lo ng匆。ti七y Poin贬e 刃二VarP tr(功少砚。七生fy)EndFu ne仁土onw w w.c e,一十嘴一书冲一:一小月- 口_ 口资J一衬一二-一、Pr土va仁eFu n etio nHa v eBe enNoti f ied)AsBo ole a nHaveBe enNoti

15、 fied二m _Noti fyEndFUnetion工nte r工o ekedln e r eme n仁P SignalNextVa rDoWh几lem_cRemaining,给工作者 时间片31e ePO,主凋代码PrivateDe ela r eFu n e七io nInte rlo eked工n e r er nentLib”ke r n e13 2.(B y ValPLo ngA日Lo ng)AsLo ng蒸pPrivatem _sign alsAsNewColle etio nPriv atem _obje etsA日NewColle etionPubl 土cSubRePo rt(

16、DataAsVa ria nt),在这里收集数据m_eRemain主ng二m _eRemaining一1EndSubPrivateFunetio nNewwo rke r()AsWo rke rD土mstrKeyAsStr立ngSetNewwo rke r二Cr e反teobje et(“Pr o.Wo rke r“)日tr义ey,C Str(Objp tr(Newwo rke r) )n _Obje et6.AddNe , J闪o rke r3trKeym _S立gn als.AddNewwo rke r.Notifypointe r,日trKe丫EndFU n Ctio nPr主vateSubS主gna1Wo rke r s()oimP gign alAsva rian七ForEa ehPsignal工n印w esign als工nte rlo ekedlne r eme n七p sign a工Ne Xt,发一次信号就够了getm _S主gnals之No

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 行业资料 > 其它行业文档

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号