摘要:[VB.NET] 背景執行 - Backgroundworker + Progressbar
在 window form 的程式,有些功能可能會需要執行一小段時間才能得到結果,在這段執行期間程式是陷於無回應(Hang住)。那該怎麼處理呢?就讓我們用 Backgroundworker 來將執行的程式片段放到背景去執行,並使用 Progressbar 來顯示整體的完成百分比。 --- 需要元件 --- Progressbar:顯示工作的完成度 --- 參數設定 --- Backgrou ndworker 的 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. 取消時的動作程序 -A2. 避免重複背景執行 -A3. 避免執行「取消」後繼續執行背景程式 --- 執行事件 --- -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 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 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:
Backgroundworker:將工作丟到背景執行
WorkerReportsProcess : Whether the worker will report progress.(回報執行進度)
WorkerSupportsCancellation: Whether the worker supports cancellation.(支援中途取消執行動作)
當設計一個按鈕要來中段背景執行的 process 時,可以呼叫「Me.BackgroundWorker1.CancelAsync()」來達成中斷的目的。
在「執行按鈕」用 BackgroundWorker1.IsBusy 判斷
在「todo_work」中用 worker.CancellationPending 判斷,True 表示已執行取消。
For k = 1 To numberToCompute
End If