2016-09-08 50 views
0

我想使用BackgroundWorker實現一個進度條。VB.net - 使用BackgroundWorker的進度條

但進度條後第二隱藏自身,並沒有保持領先直到終點。不知道爲什麼。

下面是我的表單代碼:

Private Sub btnProgressBarPOC_Click(sender As Object, e As EventArgs) Handles btnProgressBarPOC.Click 
    BackgroundWorker = New BackgroundWorker() 
    BackgroundWorker.WorkerReportsProgress = True 
    autoResetEvent = New AutoResetEvent(False) 
    ProgressBar = New frmProgressBar(BackgroundWorker) 
    ProgressBar.ShowDialog() 

    autoResetEvent.WaitOne() 
    MsgBox("Main Done", vbInformation) 
End Sub 

Sub Processing() Handles BackgroundWorker.DoWork 
    BackgroundWorker.ReportProgress(33) 
    Threading.Thread.Sleep(5000) 

    BackgroundWorker.ReportProgress(66) 
    Threading.Thread.Sleep(5000) 

    BackgroundWorker.ReportProgress(100) 

    MsgBox("Background Done", vbInformation) 
    AutoResetEvent.Set() 
End Sub 

而下面是我的代碼在其中包含進度:

Imports System.ComponentModel 

Public Class frmProgressBar 

    Private WithEvents _BGW As System.ComponentModel.BackgroundWorker 
    Private _TaskInProgress As String 

    Public WriteOnly Property TaskInProgress() 
     Set(value) 
      _TaskInProgress = value 
      _BGW.ReportProgress(1) 
     End Set 
    End Property 

    Public Sub New(ByVal BGW As System.ComponentModel.BackgroundWorker) 
     _BGW = BGW 
     InitializeComponent() 
    End Sub 

    Private Sub frmProgress_Shown(sender As Object, e As System.EventArgs) Handles Me.Shown 
     If Not IsNothing(_BGW) Then 
      _BGW.RunWorkerAsync() 
     End If 
    End Sub 

    Private Sub _BGW_ProgressChanged(sender As Object, e As System.ComponentModel.ProgressChangedEventArgs) Handles _BGW.ProgressChanged 
     progressBar.Value = e.ProgressPercentage 

     If Me.Text <> _TaskInProgress Then 
      Me.Text = _TaskInProgress 
     End If 
    End Sub 

    Private Sub _BGW_RunWorkerCompleted(sender As Object, e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles _BGW.RunWorkerCompleted 
     Me.Close() 
     _TaskInProgress = "" 
    End Sub 

    'Private Sub _BGW_DoWork(sender As Object, e As DoWorkEventArgs) Handles _BGW.DoWork 
    ' Do While True 
    '  ' Has the background worker be told to stop? 
    '  If _BGW.CancellationPending Then 
    '   ' Set Cancel to True 
    '   e.Cancel = True 
    '   Exit Do 
    '  End If 
    '  System.Threading.Thread.Sleep(2000) ' Sleep for 1 Second 
    ' Loop 
    'End Sub 
End Class 

我已經上傳我的項目在這裏: https://drive.google.com/file/d/0B7gzonuQsNbvaDZvR3ltSl9WNTg/view?usp=sharing

+1

哦,我們編織的是什麼糾結的網。沒有明顯的錯誤,發佈的代碼按預期運行。您正在忽略RunWorkerComdable事件處理程序中的e.Error屬性,從來沒有這樣做。並擺脫AutoResetEvent,它沒有任何用處。 –

+0

您能否將您的工作版本上傳到某個地方?因爲它仍然沒有按預期爲我工作。 – Tejas

+0

@HansPassant仍有問題。我已經在這裏上傳了我的項目,請問您可以通過在您的最後跑步看看嗎? https://drive.google.com/file/d/0B7gzonuQsNbvaDZvR3ltSl9WNTg/view?usp=sharing – Tejas

回答

0

下面是更正後的代碼工作得很好:這是 造成這個問題

Public Class frmMisc 
    Private WithEvents BackgroundWorker As BackgroundWorker, ProgressBar As frmProgressBar 

    Private Sub btnProgressBarPOC_Click(sender As Object, e As EventArgs) Handles btnProgressBarPOC.Click 
     Call RunProcessing() 

     MsgBox("Main Done", vbInformation) 
    End Sub 

    Sub RunProcessing() 
     BackgroundWorker = New BackgroundWorker() 
     BackgroundWorker.WorkerReportsProgress = True 
     ProgressBar = New frmProgressBar(BackgroundWorker) 
     ProgressBar.ShowDialog() 
    End Sub 

    Sub Processing() Handles BackgroundWorker.DoWork 
     BackgroundWorker.ReportProgress(33, "Step-1") 
     Threading.Thread.Sleep(3000) 

     BackgroundWorker.ReportProgress(66, "Step-2") 
     Threading.Thread.Sleep(2000) 

     BackgroundWorker.ReportProgress(100, "Step-3") 
    End Sub 
End Class 

Public Class frmProgressBar 

    Private WithEvents _BGW As System.ComponentModel.BackgroundWorker 
    Private _TaskInProgress As String 

    Public Sub New(ByVal BGW As System.ComponentModel.BackgroundWorker) 
     _BGW = BGW 
     InitializeComponent() 
    End Sub 

    Private Sub frmProgress_Shown(sender As Object, e As System.EventArgs) Handles Me.Shown 
     If Not IsNothing(_BGW) Then 
      _BGW.RunWorkerAsync() 
     End If 
    End Sub 

    Private Sub _BGW_ProgressChanged(sender As Object, e As System.ComponentModel.ProgressChangedEventArgs) Handles _BGW.ProgressChanged 
     progressBar.Value = e.ProgressPercentage 

     Me.Text = e.UserState 
    End Sub 

    Private Sub _BGW_RunWorkerCompleted(sender As Object, e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles _BGW.RunWorkerCompleted 
     Me.Close() 
     _TaskInProgress = "" 
    End Sub 
End Class 

我ProgressChanged之外,甚至做了Me.Text。 感謝@Hans提供關於此的提示!

0

你不需要d您可以處理RunWorkerCompleted事件的AutoReset事件。目前您正在阻止UI線程。

從RunWorkerAsync中移除msgbox,並且應該在你的UI線程上處理。

我懷疑它的一個異常導致RunWorkerAsync退出,因此請檢查RunWorkerCompleted事件中的錯誤代碼。這可能是由您的TaskInProgress屬性引起的,該屬性通過迂迴的方式與文本框交互,儘管它位於後臺線程上。

取而代之的是更新TaskInProgress文本框,將其作爲額外參數發送給ReportProgress並從進度框中取回。

BackgroundWorker.ReportProgress(33, "Hello") 

Private Sub _BGW_ProgressChanged(sender As Object, e As System.ComponentModel.ProgressChangedEventArgs) Handles _BGW.ProgressChanged 
    Me.Text = CStr(e.UserState) 
    .... 
+0

但是如果我沒有實現AutoResetEvent,主線程在BackgroundWorker之前結束。我需要主線程來等待BackgroundWorekr完成。有沒有其他方法可以做到這一點? – Tejas

+0

從我的代碼中可以看到,進度窗體的ShowDialog()方法應該阻塞,直到後臺工作完成。你的主線程不會退出,直到你關閉你的主窗體...這只是按鈕點擊處理程序,將退出 – FloatingKiwi

+0

我剛剛刪除AutoResetEvent後嘗試。現在RunWorkerCompleted甚至也沒有調用過。我有我的斷點,它從未到達那裏。我認爲主線程以某種方式殺死了後臺工作者。 – Tejas