VB.Net Use BackgroundWorker To Improved User Experience — VB.Net 使用 BackgroundWorker 增加使用者經驗上

大家有沒有試過在WinForm 中, 需要處理一些比較繁複的Process
或要使用到WebService/ 要在Database 中 處理一些需時比較長的Query

如果有的話, 相信大家都會在WinForm 遇到Hang/ 沒有回應 [No response] 的現像
今日的網誌想向大家介紹一個方法, 可以解決這個問題的
解決需要處理一些比較繁複的Process
程式會 Hang/ 沒有回應 [No response] 的現像
令使用者可以繼續使用 這個Win Form 中的其他功能…

由於沒有一個大的Database給我嘗試 模擬 資料庫存取時的Delay
所以在這裡我會用一個For Loop 來模擬 資料庫存取時的Delay/
或電腦在運作一些十分複雜的程式碼時WinForm沒有回應的情況

首先我們建立一個新的WinForm
之後建立2個Button
放便之後做試驗
第一個Button 叫
btn_LongProcess
-我們會用這個Button來進行資料庫存取時的Delay 令到WinForm沒有回應的情況
另一個Button 叫
btn_NormalProcess
-用來當作一些正常的WinForm動作E.G. 一些很快得到回應的動作
在這個Example我用他來做一個MessageBox PopUp

之後可以在右手面的工具列[Toolbox] 的”All Windows Forms” Section 上
BackgroundWorker 拖曳到你的WinForm中

之後便可以設定這個BackgroundWorker 屬性
通常我都會把他的名稱改成bg_Worker 放便使用

BackGroundWorker 屬性
WorkerReportsProgress -是用來設定這個BackgroundWorker會否匯報他的進度
WorkerSupportsCancellation — 用來設定這個BackgroundWorker能不能支援取消這個動作

BackGroundWorker Event
BackGroundWorker 有三個 Event
DoWork, ProgressChanged, RunWorkerCompleted

DoWork – 這是最主要的Event 因為我們主要是使用BackGroundWork DoWork Event 來幫我們做事的, 我們可以把要執行的功能放住這個, 用他來幫我們執行一些比較複雜/會令到WinForm顯示沒有回應的功能 這個BackGroundWorker 可以幫我們把這些程序在背後執行, 所以這便可以避免WinForm假死了

ProgressChanged – 我們可以用ProgressChanged Event 來匯報在DoWork Event 執行的進度[要把WorkerReportsProgress屬性設定成True 才可以使用這個Event 的 ]
RunWorkerCompleted – 當DoWork Event 執行的 程序完成時 RunWorkerCompleted Event 就會被執行
我們可以在這三個Event上用Double Click, 去建立這三個Event 的程式碼

ProgressChanged, RunWorkerCompleted WorkerSupportsCancellation 會在將來的網誌上加以說明

設定好介面後我們終端機可以開始寫程式碼了
WinForm中Double Click, 令我們開啟 Form_Load Event

Control.CheckForIllegalCrossThreadCalls = False 去解決Cross Thread Operation , 如果不加這句的話當

你的BackGroundWorker 在作時,如果你按你WinForm上的任何一個控制, 他可能會發出錯誤信息的
E.G.

Private Sub ShareChiWaiBGWorker_Load(ByVal sender As System.Object, ByVal e As System.EventArgs)Handles MyBase.Load

Control.CheckForIllegalCrossThreadCalls = False '要這樣才可以解決Cross Thread Operation的問題
End Sub

btn_NormalProcess Click Event
加入以下程式碼, 當使用者按下btn_NormalProcess 時, 他會PopUp 現時的時間

 

Private Sub btn_NormalProcess_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)Handles btn_NormalProcess.Click
MsgBox(Now)
End Sub

以下是我寫的用來擬一些Long Process的Code

Public Sub LongProcess() '用來模擬一些Long Process的Code
Dim info As Integer = 0
For i As Integer = 0 To 999999
For j As Integer = 0 To 99999
info = i + j
Next
Next
btn_LongProcess.Text = Now '完成時候 Update 這個Button 的文字為現在的時間
End Sub

btn_LongProcessClick Event
如果我們直接執行這個LongProcess() method 你的WinForm 應該會出現沒有回應的
E.G.

Private Sub btn_LongProcess_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)Handles btn_LongProcess.Click
LongProcess()
End Sub

–我們可以測試一下沒有用BackGroundWorker時 的情況應該會出現沒有回應的

所以我們可以用以把 LongProcess() 這個功能放進bg_Worker.DoWork Event中
待這個BackGroundWorker 幫我們執行LongProcess()
E.G.

Private Sub bg_Worker_DoWork(ByVal sender As System.Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles bg_Worker.DoWork
LongProcess()
End Sub

之後我們可以更改我們的btn_LongProcess 的Click Event

Private Sub btn_LongProcess_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)Handles btn_LongProcess.Click
If Not bg_Worker.IsBusy Then '查看BackGroundWorker是不是正成忙碌中, 如果不是的話便執行
bg_Worker.RunWorkerAsync()
End If
End Sub

現在可以再測試一下, 沒有回應的情況應該不會出現了, 而且使用都可以任意凡移動這個WinForm和按下btn_NormalProcess 時會看到現時的時間

LongProcess完成了

這證明了BackGroundWorker 可以解決WinForm 在執行一些比較,需時的程序時出現沒有回應的情況

將來的網誌我會說說ProgressChanged, RunWorkerCompleted 和WorkerSupportsCancellation 的用法和如果好好運用BackGroundWorker去增加使用者經驗

Hope you find it useful, 歡迎大家給我一些意見, 令我可以發多一些有用的文章/教學,Improve 自己

全部的原始碼

Public Class ShareChiWaiBGWorker

Private Sub bg_Worker_DoWork(ByVal sender As System.Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles bg_Worker.DoWork
LongProcess()
End Sub

Private Sub bg_Worker_ProgressChanged(ByVal sender As System.Object, ByVal e As System.ComponentModel.ProgressChangedEventArgs) Handles bg_Worker.ProgressChanged

End Sub

Private Sub bg_Worker_RunWorkerCompleted(ByVal sender As System.Object, ByVal e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles bg_Worker.RunWorkerCompleted

End Sub

Private Sub ShareChiWaiBGWorker_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Control.CheckForIllegalCrossThreadCalls = False '要這樣才可以解決Cross Thread Operation 的問題
End Sub

Public Sub LongProcess() '用來模擬一些Long Process的Code
Dim info As Integer = 0
For i As Integer = 0 To 999999
For j As Integer = 0 To 9999
info = i + j
Next
Next
btn_LongProcess.Text = Now '完成時候 Update 這個Button 的文字為現在的時間
End Sub

Private Sub btn_LongProcess_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btn_LongProcess.Click
If Not bg_Worker.IsBusy Then '查看BackGroundWorker是不是正成忙碌中, 如果不是的話便執行
bg_Worker.RunWorkerAsync()
End If
End Sub

Private Sub btn_NormalProcess_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btn_NormalProcess.Click
MsgBox(Now)
End Sub
End Class

Leave a Reply