開發(fā)者一直要求微軟為VB加入更多的多線程功能,對于VB.NET也是這樣。VB6已經(jīng)支持建立多線程的EXE、DLL和OCX。不過使用多線程這個詞語,可能也不太確切。因此VB6僅支持運(yùn)行多個單線程的單元。一個單元實際上是代碼執(zhí)行的空間,而單元的邊界限制了代碼訪問任何單元以外的事物。
VB.NET就不同了,它支持建立自由線程(free-threaded)的應(yīng)用。這意味著多個線程可以訪問同樣一套的共享數(shù)據(jù)。本文的以下部分將討論一下多線程的一些基本點。
問題
雖然VB6支持多個單線程的單元,不過它并不支持一個自由線程的模型,即不允許多個線程使用同一套數(shù)據(jù)。在許多的情況下,你需要建立一個新的線程來進(jìn)行后臺的處理,這樣可提高應(yīng)用的可用性,否則,一個長的處理就可以令程序的響應(yīng)變得很慢,例如你按下表格上的一個取消按鈕,卻很久都沒有響應(yīng)。
解決辦法
由于VB.NET使用了CLR(Common Language Runtime),從而擁有了許多的新特性,其中的一個是可以創(chuàng)建自由線程的應(yīng)用。
使用線程
在VB.NET中,運(yùn)用線程是很簡單的。我們將在后面涉及其中的細(xì)節(jié),現(xiàn)在我們首先來創(chuàng)建一個簡單的表格,它使用一個新的線程來運(yùn)行一個后臺處理。第一件要做的事情是創(chuàng)建運(yùn)行在新線程上的后臺任務(wù)。以下的代碼執(zhí)行一個相當(dāng)長的運(yùn)行處理--一個無限的循環(huán):
Private Sub BackgroundProcess()
Dim i As Integer = 1
Do While True
ListBox1.Items.Add("Iterations: " + i)
i += 1
Loop
End Sub
這段代碼無限地循環(huán),并且在每次執(zhí)行時為表格上的一個列表框加入一個項目。如果你對VB.NET不熟悉的話,你將會發(fā)現(xiàn)這段代碼和VB6的有一些區(qū)別:
. 在聲明變量Dim i As Integer = 1時賦值
. 使用+=操作符i += 1代替i = i + 1
. 沒有使用Call關(guān)鍵字
一旦我們擁有了一個工作的處理,我們就需要將這段代碼分配給一個線程處理,并且啟動它。為此我們要使用線程對象(Thread object),它是.NET架構(gòu)類中System.Threading命名空間的一部分。在實例化一個新的線程類時,我們將要在線程類構(gòu)造器執(zhí)行的代碼塊的一個引用傳送給它。以下的代碼創(chuàng)建一個新的線程對象,并且將BackgroundProcess的一個引用傳送給它:
Dim t As Thread
t = New Thread(AddressOf Me.BackgroundProcess)
t.Start()
AddressOf操作符創(chuàng)建了一個到BackgroundProcess方法的委派對象。在VB.NET中,一個委派是一個類型安全、面向?qū)ο蟮暮瘮?shù)指針。在實例化該線程后,你可以通過調(diào)用線程的Start()方法來開始執(zhí)行代碼。
控制線程
在線程啟動后,你可以通過線程對象的一個方法來控制它的狀態(tài)。你可以通過調(diào)用Thread.Sleep方法來暫停一個線程的執(zhí)行,這個方法可以接收一個整型值,用來決定線程休眠的時間。拿前面的例子來說,如果你想讓列表項目增加的速度變慢,可以在其中放入一個sleep方法的調(diào)用:
Private Sub BackgroundProcess()
Dim i As Integer = 1
Do While True
ListBox1.Items.Add("Iterations: " + i)
i += 1
Thread.CurrentThread.Sleep(2000)
Loop
End Sub
CurrentThread是一個public static的屬性值,可讓你得到當(dāng)前運(yùn)行線程的一個引用。
你還可以通過調(diào)用Thread.Sleep (System.Threading.Timeout.Infinite)來讓線程進(jìn)入休眠狀態(tài),有點特別的是,這個調(diào)用的休眠時間是不確定的。要中斷這個休眠,你可以調(diào)用Thread.Interrupt方法。
與休眠和中斷類似的是掛起和恢復(fù)。掛起可讓你暫停一個線程,直到另一個線程調(diào)用Thread.Resume為止。休眠和掛起的區(qū)別是,后者并不立刻讓線程進(jìn)入一個等待的狀態(tài),線程并不會掛起,直到.NET runtime認(rèn)為現(xiàn)在已經(jīng)是一個安全的地方來掛起它了,而休眠則會立刻讓線程進(jìn)入一個等待的狀態(tài)。
最后要介紹的是Thread.Abort,它會停止一個線程的執(zhí)行。在我們的那個簡單例子中,如果要加入一個按鈕來停止處理,很簡單,我們只要調(diào)用Thread.Abort方法就行了,如下所示:
Private Sub Button2_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Button2.Click
t.Abort()
End Sub
這就是多線程的強(qiáng)大之處。用戶界面的響應(yīng)很好,因為它運(yùn)行在一個單獨(dú)的線程中,而后臺的處理運(yùn)行在另外一個線程中。在用戶按下取消按鈕時,便會馬上得到響應(yīng),并且停止處理。
上面的例子只是一個相當(dāng)簡單的應(yīng)用。在編程時,你還需要使用到多線程的許多復(fù)雜特性。其中的一個問題是如何將程序的數(shù)據(jù)由線程類的構(gòu)造器傳入或者傳出,也就是說,對于放到另外一個線程中的過程,你既不能傳參數(shù)給它,也不能由它返回值。這是由于你傳入到線程構(gòu)造器的過程是不能擁有任何的參數(shù)或者返回值的。為了解決這個問題,可以將你的過程封裝到一個類中,這樣方法的參數(shù)就可使用類中的字段。
這里我們舉一個簡單的例子,如果我們要計算一個數(shù)的平方,即:
![]() | ![]() .. 定價:¥225 優(yōu)惠價:¥213 更多書籍 |
![]() | ![]() .. 定價:¥133 優(yōu)惠價:¥133.0 更多書籍 |