Personálmente por cosas como esta nunca me gustó el BackGroundWorker.
La forma correcta de pausar/reusmir un BackgroundWorker es usando un ManualResetEvent:
EDITO: Fíjate que debes especificar manuálmente los lugares en donde el procedimiento se puede pausar (_busy.WaitOne), y esto debes especificarlo sólamente en el eventhandler DoWork.
Imports System.ComponentModel
Public Class BackgroundWork
Private _busy As New Threading.ManualResetEvent(True)
Private WithEvents MyWorker As New BackgroundWorker
Public Sub StartBackgroundTask()
MsgBox("Starting the Thread...")
MyWorker.WorkerSupportsCancellation = True
MyWorker.WorkerReportsProgress = True
MyWorker.RunWorkerAsync()
End Sub
Private Sub MyWorker_DoWork(ByVal sender As Object, ByVal e As DoWorkEventArgs) _
Handles MyWorker.DoWork
For i = 1 To 5
_busy.WaitOne(Threading.Timeout.Infinite)
MyWorker.ReportProgress(MsgBox("Thread is working... " & CStr(i)))
Next i
End Sub
Private Sub MyWorker_RunWorkerCompleted(ByVal sender As Object, ByVal e As RunWorkerCompletedEventArgs) _
Handles MyWorker.RunWorkerCompleted
MsgBox("Thread Done!")
End Sub
Public Sub PauseWorker()
If MyWorker.IsBusy Then
_busy.Reset()
MsgBox("Thread Paused!")
End If
End Sub
Public Sub ContinueWorker()
_busy.[Set]()
MsgBox("Thread Resumed!")
End Sub
End Class
EDITO 2: Un ejemplo mejor elaborado:
Entonces, desde el thread principal puedes hacer esto:
Saludos
La forma correcta de pausar/reusmir un BackgroundWorker es usando un ManualResetEvent:
EDITO: Fíjate que debes especificar manuálmente los lugares en donde el procedimiento se puede pausar (_busy.WaitOne), y esto debes especificarlo sólamente en el eventhandler DoWork.
Imports System.ComponentModel
Public Class BackgroundWork
Private _busy As New Threading.ManualResetEvent(True)
Private WithEvents MyWorker As New BackgroundWorker
Public Sub StartBackgroundTask()
MsgBox("Starting the Thread...")
MyWorker.WorkerSupportsCancellation = True
MyWorker.WorkerReportsProgress = True
MyWorker.RunWorkerAsync()
End Sub
Private Sub MyWorker_DoWork(ByVal sender As Object, ByVal e As DoWorkEventArgs) _
Handles MyWorker.DoWork
For i = 1 To 5
_busy.WaitOne(Threading.Timeout.Infinite)
MyWorker.ReportProgress(MsgBox("Thread is working... " & CStr(i)))
Next i
End Sub
Private Sub MyWorker_RunWorkerCompleted(ByVal sender As Object, ByVal e As RunWorkerCompletedEventArgs) _
Handles MyWorker.RunWorkerCompleted
MsgBox("Thread Done!")
End Sub
Public Sub PauseWorker()
If MyWorker.IsBusy Then
_busy.Reset()
MsgBox("Thread Paused!")
End If
End Sub
Public Sub ContinueWorker()
_busy.[Set]()
MsgBox("Thread Resumed!")
End Sub
End Class
EDITO 2: Un ejemplo mejor elaborado:
Código
' BackgroundWorker Example ' ' // By Elektro H@cker #Region " Usage Examples " 'Public Class Form1 ' Private MyWorker As New BackgroundWork ' Private Shadows Sub Load() Handles MyBase.Load ' MyWorker.StartBackgroundTask() ' End Sub ' Private Sub Button_Pause_Click() Handles Button_Pause.Click ' MyWorker.Pause() ' End Sub ' Private Sub Button_Resume_Click() Handles Button_Resume.Click ' MyWorker.Resume() ' End Sub ' Private Sub Button_Cancel_Click() Handles Button_Cancel.Click ' MyWorker.Cancel() ' End Sub 'End Class #End Region #Region " BackgroundWorker " Public Class BackgroundWork ''' <summary> ''' The BackgroundWorker object. ''' </summary> Private WithEvents MyWorker As New System.ComponentModel.BackgroundWorker ''' <summary> ''' ManualResetEvent object to pause/resume the BackgroundWorker. ''' </summary> Private _busy As New Threading.ManualResetEvent(True) ''' <summary> ''' This will start the BackgroundWorker. ''' </summary> Public Sub StartBackgroundTask() MsgBox("Starting the Thread...") MyWorker.WorkerSupportsCancellation = True MyWorker.WorkerReportsProgress = True MyWorker.RunWorkerAsync() End Sub ''' <summary> ''' This is the work to do on background. ''' </summary> Private Sub MyWorker_DoWork(ByVal sender As Object, ByVal e As System.ComponentModel.DoWorkEventArgs) _ Handles MyWorker.DoWork For i = 1 To 5 If MyWorker.CancellationPending = True Then e.Cancel = True Exit For Else _busy.WaitOne(Threading.Timeout.Infinite) ' Indicate that here can be paused the Worker. MyWorker.ReportProgress( MsgBox("Thread is working... " & i) ) End If Next i End Sub ''' <summary> ''' This happens when the BackgroundWorker is completed. ''' </summary> Private Sub MyWorker_RunWorkerCompleted(ByVal sender As Object, ByVal e As System.ComponentModel.RunWorkerCompletedEventArgs) _ Handles MyWorker.RunWorkerCompleted If e.Cancelled = True Then MsgBox("Thread cancelled") ElseIf e.Error IsNot Nothing Then MsgBox("Thread error") Else MsgBox("Thread Done!") End If End Sub ''' <summary> ''' This will pause the BackgroundWorker. ''' </summary> Public Sub Pause() If MyWorker.IsBusy Then _busy.Reset() MsgBox("Thread Paused!") End If End Sub ''' <summary> ''' This will resume the BackgroundWorker. ''' </summary> Public Sub [Resume]() _busy.[Set]() MsgBox("Thread Resumed!") End Sub ''' <summary> ''' This will cancel the BackgroundWorker. ''' </summary> Public Sub Cancel() _busy.[Set]() ' Resume worker if it is paused. MyWorker.CancelAsync() ' Cancel it. End Sub End Class #End Region
Entonces, desde el thread principal puedes hacer esto:
Código
Public Class Form1 Private MyWorker As New BackgroundWork Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load MyWorker.StartBackgroundTask() End Sub Private Sub Button_Pause_Click() Handles Button_Pause.Click MyWorker.PauseWorker() End Sub Private Sub Button_Resume_Click() Handles Button_Resume.Click MyWorker.ContinueWorker() End Sub End Class
Saludos
Mmm... creo que seguiré usando la forma tradicional de usar hilos en background. Jeje.
Muchísimas gracias.