明輝手游網(wǎng)中心:是一個(gè)免費(fèi)提供流行視頻軟件教程、在線學(xué)習(xí)分享的學(xué)習(xí)平臺(tái)!

在 Visual Basic .NET 中完成后臺(tái)進(jìn)程(3)

[摘要]創(chuàng)建顯示的窗體最后,我們可以創(chuàng)建窗體,將其用于啟動(dòng)或取消后臺(tái)進(jìn)程。該窗體還將顯示活動(dòng)和狀態(tài)信息。打開 Form1 的設(shè)計(jì)器并添加兩個(gè)按鈕(btnStart 和 btnRequestCancel)、兩個(gè)標(biāo)簽(Label1 和 Label2)、一個(gè) ProgressBar (ProgressBar1)...

創(chuàng)建顯示的窗體

最后,我們可以創(chuàng)建窗體,將其用于啟動(dòng)或取消后臺(tái)進(jìn)程。該窗體還將顯示活動(dòng)和狀態(tài)信息。

打開 Form1 的設(shè)計(jì)器并添加兩個(gè)按鈕(btnStartbtnRequestCancel)、兩個(gè)標(biāo)簽(Label1Label2)、一個(gè) ProgressBar (ProgressBar1) 和一個(gè) ActivityBar (ActivityBar1),如圖 7 所示。

在 Visual Basic .NET 中實(shí)現(xiàn)后臺(tái)進(jìn)程(三)

圖 7:Form1 控件的布局

該窗體需要實(shí)現(xiàn) IClient,以便 Controller 對(duì)象與之交互:

Imports BackgroundPublic Class Form1  Inherits System.Windows.Forms.Form  Implements IClient

該窗體還需要 Controller 對(duì)象和一個(gè)標(biāo)志,用以跟蹤后臺(tái)操作是處于活動(dòng)狀態(tài)還是處于完成狀態(tài)。

  Private mController As New Controller(Me)  Private mActive As Boolean

然后,我們可以添加方法,以實(shí)現(xiàn)由 IClient 定義的接口。建議將這些方法放在 Region 中,以表示它們實(shí)現(xiàn)的是輔助接口:

#Region " IClient "  Private Sub TaskStarted(ByVal Controller As Controller) _      Implements IClient.Start    mActive = True    Label1.Text = "Starting"    Label2.Text = "0%"    ProgressBar1.Value = 0    ActivityBar1.Start()  End Sub  Private Sub TaskStatus(ByVal Text As String) _      Implements IClient.Display    Label1.Text = Text    Label2.Text = CStr(mController.Percent) & "%"    ProgressBar1.Value = mController.Percent  End Sub  Private Sub TaskFailed(ByVal e As Exception) _      Implements IClient.Failed    ActivityBar1.Stop()    Label1.Text = e.Message    MsgBox(e.ToString)    mActive = False  End Sub  Private Sub TaskCompleted(ByVal Cancelled As Boolean) _      Implements IClient.Completed    Label1.Text = "Completed"    Label2.Text = CStr(mController.Percent) & "%"    ProgressBar1.Value = mController.Percent    ActivityBar1.Stop()    mActive = False  End Sub#End Region

請(qǐng)注意,這一段代碼中的所有內(nèi)容均與線程無關(guān),其中的每一部分代碼都可以在我們得知后臺(tái)操作的狀態(tài)時(shí)做出相應(yīng)的響應(yīng)。每次響應(yīng)后,我們都會(huì)更新顯示以表明進(jìn)程的狀態(tài)和完成百分比(以文字的形式或通過 ProgressBar 顯示),并啟動(dòng)和停止 ActivityBar 控件。

mActive 標(biāo)志非常重要。如果用戶在輔助線程處于活動(dòng)狀態(tài)時(shí)關(guān)閉窗體,應(yīng)用程序可能會(huì)掛起或變得不穩(wěn)定。要防止出現(xiàn)這種情況,我們可以打斷窗體的 Closing 事件并取消關(guān)閉嘗試(如果后臺(tái)進(jìn)程處于活動(dòng)狀態(tài))。

  Private Sub Form1_Closing(ByVal sender As Object, _    ByVal e As System.ComponentModel.CancelEventArgs) _    Handles MyBase.Closing    e.Cancel = mActive  End Sub

我們還可以選擇在這種情況下初始化取消操作,但是這取決于特定的應(yīng)用程序要求。

其余的代碼都是為了實(shí)現(xiàn)按鈕的 Click 事件。

  Private Sub btnStart_Click(ByVal sender As System.Object, _      ByVal e As System.EventArgs) Handles btnStart.Click    mController.Start(New Worker(2000000, 100))  End Sub  Private Sub btnStop_Click(ByVal sender As System.Object, _      ByVal e As System.EventArgs) Handles btnStop.Click    Label1.Text = "Cancelling ..."    mController.Cancel()  End Sub

Start(開始)按鈕只調(diào)用 Controller 對(duì)象的 Start 方法,并將 Worker 對(duì)象的實(shí)例傳遞給它。

您可能需要調(diào)整用于初始化 Worker 對(duì)象的值,以便在您的計(jì)算機(jī)上獲得所需的結(jié)果。這些特定的值提供了雙處理器 P3/450 計(jì)算機(jī)上的一個(gè)良好示例。顯然,這只是用于測(cè)試目的。真正的 Worker 對(duì)象將實(shí)現(xiàn)更有意義、運(yùn)行時(shí)間更長(zhǎng)的進(jìn)程。

Cancel(取消)按鈕將調(diào)用 Controller 對(duì)象的 Cancel 方法,同時(shí)還會(huì)更新顯示,以表明已請(qǐng)求取消。請(qǐng)記住,這只是一個(gè)取消“請(qǐng)求”,在輔助線程真正停止運(yùn)行之前可能需要等待一些時(shí)間。最好能夠?yàn)橛脩籼峁┘磿r(shí)反饋,至少應(yīng)讓用戶知道系統(tǒng)已經(jīng)注意到用戶的單擊按鈕操作。

現(xiàn)在,我們可以運(yùn)行應(yīng)用程序了。單擊 Start(開始)按鈕時(shí),Worker 就應(yīng)該開始運(yùn)行,而且顯示的內(nèi)容會(huì)在運(yùn)行時(shí)更新。您可以將窗體移動(dòng)到屏幕上的任意位置,也可以與其交互,因?yàn)?UI 線程本質(zhì)上還處于空閑狀態(tài),可以隨時(shí)與您交互。

同時(shí),輔助線程在后臺(tái)進(jìn)行大量復(fù)雜的工作,并定期將狀態(tài)更新信息發(fā)送給 UI 線程以進(jìn)行顯示。

小結(jié)

多線程是一個(gè)功能強(qiáng)大的工具,我們可以在每次需要執(zhí)行長(zhǎng)時(shí)間運(yùn)行的任務(wù)時(shí)使用該工具。我們可以用它運(yùn)行輔助代碼,而無需綁定用戶界面。但同時(shí)要注意,多線程操作非常復(fù)雜,要正確操作并不容易,而且調(diào)試起來也比較困難。

盡管不一定能夠?qū)崿F(xiàn),但我們還是應(yīng)該盡量為每個(gè)輔助線程提供一組它可以操作的獨(dú)立數(shù)據(jù)。要達(dá)到這個(gè)目的,最簡(jiǎn)單的方法就是為每個(gè)線程創(chuàng)建一個(gè)對(duì)象,對(duì)象中包含該線程可以操作的數(shù)據(jù)以及完成工作所需的代碼。

通過實(shí)現(xiàn)結(jié)構(gòu)化的架構(gòu),使之充當(dāng)輔助線程和 UI 線程之間的媒介,我們可以大大簡(jiǎn)化編寫多線程代碼和 UI 以對(duì)其進(jìn)行控制的過程。本文就介紹了這樣一個(gè)架構(gòu),您可以根據(jù)需要使用或進(jìn)行調(diào)整,以滿足特定的應(yīng)用需要。