本帖最后由 ganlinlao 于 2016-12-19 13:26 編輯
兄弟,如果你和我一樣是一個(gè)Access菜鳥(niǎo),而且是屬于無(wú)可救藥的那種,那么在過(guò)去的很多年里,你一定聽(tīng)過(guò)很多很多的人不停地告訴你,VB6、VBA是無(wú)法使用多線(xiàn)程的,以至于你忍不住相信多線(xiàn)程是VBA不可逾越的障礙。忍不住相信多線(xiàn)程對(duì)于VBA來(lái)說(shuō)只是傳說(shuō)中的詩(shī)和遠(yuǎn)方,遠(yuǎn)方遙遠(yuǎn)得一無(wú)所有。而我們這樣的菜鳥(niǎo)只剩下眼前單線(xiàn)程的茍且,并把這種茍且當(dāng)成一種美好、快樂(lè)和滿(mǎn)足。
是的,他們說(shuō)的沒(méi)錯(cuò),VBA有著一顆易碎而脆弱的玻璃心。
在過(guò)去的十多年里,無(wú)數(shù)的人都試圖在vba里使用多線(xiàn)程,但幾乎都倒在淋漓的血泊和無(wú)盡的讓人抓狂的自虐中。
今天讓我們揭開(kāi)在VBA中使用多線(xiàn)程神秘的面紗,讓這個(gè)沐浴著陽(yáng)光梳著長(zhǎng)發(fā)的美少女,能對(duì)你輕輕回眸一笑。
今天的cpu絕大多數(shù)是雙核雙線(xiàn)程、雙核4線(xiàn)程、四核四線(xiàn)程、四核八線(xiàn)程、八核……,所以在VBA中使用多線(xiàn)程來(lái)提高運(yùn)行效率顯得很有必要。而且在一些場(chǎng)景下,你也很渴望能使用多線(xiàn)程來(lái)改善慘不忍睹的狀況,比如在excel中的多個(gè)大循環(huán)計(jì)算會(huì)讓excel表很卡,大批量復(fù)制文件,下載網(wǎng)絡(luò)數(shù)據(jù)……都很容易造成access或excel界面出現(xiàn)“假死”。
在VBA中,其實(shí)可以使用不少的線(xiàn)程庫(kù),比如vbthreadfacory,vbrichclient5中線(xiàn)程庫(kù)……事實(shí)上你能找到不少的vb線(xiàn)程庫(kù),前面兩種線(xiàn)程庫(kù)是我了解到的比較穩(wěn)定而且功能比較完備的線(xiàn)程庫(kù)。今天我在這里介紹是另一種更加簡(jiǎn)單易用的線(xiàn)程庫(kù),雖然它功能不那么完備,但卻是簡(jiǎn)單明了,用法簡(jiǎn)單直接,能讓我們更容易理解多線(xiàn)程的概念和入門(mén)使用。
關(guān)于進(jìn)程、線(xiàn)程的概念,你可以百度或詳見(jiàn)我的空間日志。
Access或excel的主線(xiàn)程:Access.exe是一個(gè)進(jìn)程,access.exe會(huì)為每一個(gè)打開(kāi)的access文件(指的是客戶(hù)端)分配一個(gè)線(xiàn)程(這里我們暫且稱(chēng)此線(xiàn)程是主線(xiàn)程),這個(gè)Access文件中所有的Form,控件都在同一個(gè)線(xiàn)程中運(yùn)行。注意是所有的Form及其下面的控件!同樣的,excel.exe會(huì)為每一個(gè)打開(kāi)的workbook分配一個(gè)線(xiàn)程,這個(gè)workbook中所有的表(包括每一個(gè)表及其下面的userform及控件)都運(yùn)行在同一個(gè)線(xiàn)程中。了解這一點(diǎn)蠻重要的,因?yàn)檫@能讓我們更注意保護(hù)子線(xiàn)程的安全,減少access或excel崩潰。
Access或excel的主線(xiàn)程消息處理:事件是一種消息,而消息是一種線(xiàn)性隊(duì)列,所以所有子線(xiàn)程跟主線(xiàn)程的通訊,最終都會(huì)串口化成主線(xiàn)程的事件(消息),最終在主線(xiàn)程那里變成單線(xiàn)程的事件。主線(xiàn)程無(wú)法在同一時(shí)間點(diǎn)處理兩個(gè)以上的事件,而這一點(diǎn)恰恰是access或excel在使用多線(xiàn)程上最容易引起崩潰的原因。而且要注意,access或excel的vba處理消息能力很差(因?yàn)槲覀儾恢?/font>access處理完一個(gè)事件之后會(huì)不會(huì)在內(nèi)部自動(dòng)觸發(fā)另一個(gè)我們不知道的事件,據(jù)我所知,excel內(nèi)部事件遠(yuǎn)遠(yuǎn)比vba能用到的事件多得多),相比較而言,編譯過(guò)的vb6程序在多線(xiàn)程方面則要穩(wěn)定得多了。
如何避免讓access在同一時(shí)間點(diǎn)處理兩個(gè)事件,是我們使用vba多線(xiàn)程排在首位任務(wù)。任何引發(fā)access或excel在同一時(shí)間點(diǎn)處理兩個(gè)以上事件,access或excel一定會(huì)崩潰。
在vba中使用多線(xiàn)程,以下是我個(gè)人簡(jiǎn)單的經(jīng)驗(yàn),以后你使用多了,也可以總結(jié)一下并寫(xiě)出來(lái),讓其他人少走一些彎路。
經(jīng)驗(yàn)1:在任何調(diào)試多線(xiàn)程代碼之前,一定要先保存。先保存后調(diào)試是鐵律,否則很多意外,會(huì)讓你欲哭無(wú)淚。
經(jīng)驗(yàn)2:盡量減少子線(xiàn)程跟主線(xiàn)程的通訊次數(shù)。很多的時(shí)候,其實(shí)我們只需一個(gè)子線(xiàn)程跟主線(xiàn)程通訊而已(比如我們常常只需要顯示一個(gè)進(jìn)度條就夠了)。如果進(jìn)度條需要100次跟主線(xiàn)程通訊,那么想辦法讓它減少成只有10次,跟主線(xiàn)程的通訊次數(shù)越少,越能減少讓access主線(xiàn)程同時(shí)處理兩個(gè)消息的機(jī)會(huì)。
經(jīng)驗(yàn)3:要及時(shí)主動(dòng)銷(xiāo)毀子線(xiàn)程占用的資源。不能指望access或excel自動(dòng)幫你銷(xiāo)毀。如果子線(xiàn)程占用資源沒(méi)有銷(xiāo)毀,會(huì)引發(fā)很多問(wèn)題,甚至引起崩潰。所有一般對(duì)于子線(xiàn)程,我們盡量在需要時(shí)創(chuàng)建,用完立即銷(xiāo)毀。
經(jīng)驗(yàn)4:如果是控件類(lèi),盡量用vb6編譯成dll,然后再在access中使用,我前面提到過(guò)了,vb6編譯過(guò)的dll在多線(xiàn)程方面要穩(wěn)定得多了。如果是寫(xiě)很多需要多線(xiàn)程調(diào)用的函數(shù),那用vb6編譯成dll,也會(huì)更穩(wěn)妥一些。
經(jīng)驗(yàn)5:當(dāng)一個(gè)access的form不在激活狀態(tài),最好讓它對(duì)應(yīng)的子線(xiàn)程都處在休眠狀態(tài)(掛起),當(dāng)整個(gè)access客戶(hù)端,不在激活狀態(tài),也最好讓它對(duì)應(yīng)的所有子線(xiàn)程都掛起。這樣能大大減少讓access同時(shí)處理兩個(gè)消息的機(jī)會(huì)。這也同樣適用excel。不要忘了,不管是access還是excel都是mdi多文檔程序。 |