Tengo una duda, estoy usando backgroundworker y ahora se me ocurre hacer una pausa al presionar un botón. No quiero cancelar la ejecución de este backgrounworker sino todo lo contrario, pero la verdad es que no se cómo hacerlo.
Pesaba que este control podría existir algo como:
CitarBackgroundWorker1.state
:P :¬¬
Espero que me puedan ayudar u orientarme mejor. Gracias.
Cita de: Loco.AR en 17 Diciembre 2013, 21:34 PMPesaba que este control podría existir algo como:
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 ClassEDITO 2: Un ejemplo mejor elaborado:
' 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:
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
Cita de: ElektroSoft en 18 Diciembre 2013, 07:58 AM
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:
' 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:
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.