摘要:[VB.NET] 背景執行 - Backgroundworker + Progressbar
在 window form 的程式,有些功能可能會需要執行一小段時間才能得到結果,在這段執行期間程式是陷於無回應(Hang住)。那該怎麼處理呢?就讓我們用 Backgroundworker 來將執行的程式片段放到背景去執行,並使用 Progressbar 來顯示整體的完成百分比。
--- 需要元件 ---
Backgroundworker:將工作丟到背景執行
Progressbar:顯示工作的完成度
--- 參數設定 ---
Backgrou ndworker 的
WorkerReportsProcess : Whether the worker will report progress.(回報執行進度)
WorkerSupportsCancellation: Whether the worker supports cancellation.(支援中途取消執行動作)
ProgressBar 預設不顯示 ProgressBar1.Visible = False
--- 事件執行程序 ---
-1. 點選按鈕「btn_dojob」呼叫「BackgroundWorker1.RunWorkerAsync() 」開始背景執行程式
-2. 執行「BackgroundWorker1_DoWork」並於其中執行「 todo_work(worker, e)」,todo_work 是我們要丟到背景去執行的程式片段。
-3. 當第一次 todo_work 執行完成時,會呼叫「worker.ReportProgress」回報執行完成度與執行「BackgroundWorker1_ProgressChanged」更新顯示完成百分比。
若有 UI (User Interface)事件要顯示,必須在「BackgroundWorker1_ProgressChanged」中去處理,不能在程式執行片段「 todo_work()」中去表示。todo_work 當然更不能有跟使用者互動的動作,如msgbox()之類。
-4. 都執行完成後(100%),會去執行事件「BackgroundWorker1_RunWorkerCompleted」。
-A1. 取消時的動作程序
當設計一個按鈕要來中段背景執行的 process 時,可以呼叫「Me.BackgroundWorker1.CancelAsync()」來達成中斷的目的。
-A2. 避免重複背景執行
在「執行按鈕」用 BackgroundWorker1.IsBusy 判斷
-A3. 避免執行「取消」後繼續執行背景程式
在「todo_work」中用 worker.CancellationPending 判斷,True 表示已執行取消。
--- 執行事件 ---
-1. 2個按鈕,分別為執行與取消
「執行按鈕」
Private Sub btn_dojob_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handlesbtn_dojob.Click
If BackgroundWorker1.IsBusy Then
MessageBox.Show("系統執行中")
Else
ProgressBar1.Visible = True
BackgroundWorker1.RunWorkerAsync() '起始背景執行的呼叫
End If
End Sub
「取消按鈕」
Private Sub btn_cancel_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handlesbtn_cancel.Click
If MsgBox("是否取消?" & vbCrLf & "在未按下ok前,系統仍會持續執行!", vbOKCancel, "是否中段執行") = MsgBoxResult.Ok Then
Me.BackgroundWorker1.CancelAsync()
End If
End Sub
-2. 準備執行的程式片段 todo_work()
Private Sub todo_work(ByVal worker As BackgroundWorker, ByVal e As DoWorkEventArgs)
If worker.CancellationPending Then
e.Cancel = True
Else
For k = 1 To numberToCompute
If My.Computer.Network.Ping(Server_List) Then
server_ping = ok
Else
server_ping = bad
End If
percentComplete = CInt((k / numberToCompute) * 100)
worker.ReportProgress(percentComplete) ' 回報完成率
Next
End If
End Sub
-3. Backgroundworker 事件處理
Private Sub BackgroundWorker1_DoWork(ByVal sender As System.Object, ByVal e AsSystem.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork
' 要使用 baclgroundWorker 要 Imports System.ComponentModel
Dim worker As BackgroundWorker = CType(sender, BackgroundWorker)
todo_work(worker, e) '欲背景執行的 function
End Sub
Private Sub BackgroundWorker1_ProgressChanged(ByVal sender As System.Object, ByVal e AsSystem.ComponentModel.ProgressChangedEventArgs) Handles BackgroundWorker1.ProgressChanged
Me.ProgressBar1.Value = e.ProgressPercentage
' 更新 ProgressBar1 的百分比值
End Sub
Private Sub BackgroundWorker1_RunWorkerCompleted(ByVal sender As System.Object, ByVal e AsSystem.ComponentModel.RunWorkerCompletedEventArgs) Handles BackgroundWorker1.RunWorkerCompleted
If (e.Error IsNot Nothing) Then
MessageBox.Show(e.Error.Message)
ElseIf e.Cancelled Then
MessageBox.Show("使用者取消執行!")
Else
ProgressBar1.Visible = False ' 執行完成隱藏 ProgressBar
MessageBox.Show("工作完成!")
End If
End Sub
-4. 如果想要知道程式執行是否持續執行沒被hang住,可以加入 timer 顯示來做為判斷
Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
Label2.Text = Now.ToString("HH:mm:ss.ffffff")
' Label2.Text = Format(Now(), "yy:mm:dd HH:mm:ss.ff")
End Sub
-5. 換你試試看囉!
Reference:
- http://msdn.microsoft.com/zh-tw/library/8xs8549b%28VS.80%29.aspx
- http://msdn.microsoft.com/zh-tw/library/hybbz6ke%28v=VS.80%29.aspx
- Backgroundwork 圖:http://images.cnblogs.com/cnblogs_com/happy555/backgroundworker.jpg
- http://msdn.microsoft.com/zh-tw/library/bd6xat66%28v=VS.95%29.aspx