Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- ' -------------------
- ' Info of interest...
- ' -------------------
- '
- ' BackgroundWorker Component Overview:
- ' http://msdn.microsoft.com/en-us/library/8xs8549b%28v=vs.110%29.aspx
- '
- ' Walkthrough: Multithreading with the BackgroundWorker Component:
- ' http://msdn.microsoft.com/en-us/library/ywkkz4s1.aspx
- '
- ' How to: Use a Background Worker:
- ' https://msdn.microsoft.com/es-es/library/cc221403%28v=vs.95%29.aspx
- '
- ' How to: Implement a Form That Uses a Background Operation:
- ' http://msdn.microsoft.com/en-us/library/waw3xexc%28v=vs.110%29.aspx
- #Region " Usage Examples "
- 'Public Class Form1
- '
- ' Friend MyWork As Worker
- '
- ' Private Sub Run_Click() Handles Button_Start.Click
- ' If (Me.MyWork IsNot Nothing) AndAlso (Me.MyWork.IsRunning) Then
- ' Me.MyWork.Cancel()
- ' End If
- '
- ' Me.MyWork = New Worker
- ' Me.MyWork.RunAsync()
- ' End Sub
- '
- ' Private Sub Pause_Click() Handles Button_Pause.Click
- ' Me.MyWork.Pause()
- ' End Sub
- '
- ' Private Sub Resume_Click() Handles Button_Resume.Click
- ' Me.MyWork.Resume()
- ' End Sub
- '
- ' Private Sub Cancel_Click() Handles Button_Cancel.Click
- ' Me.MyWork.Cancel()
- ' End Sub
- '
- 'End Class
- #End Region
- #Region " Option Statements "
- Option Strict On
- Option Explicit On
- Option Infer Off
- #End Region
- #Region " Imports "
- Imports System.ComponentModel
- Imports System.Diagnostics
- Imports System.Threading
- #End Region
- #Region " Worker "
- Public NotInheritable Class Worker : Implements IDisposable
- #Region " Private Fields "
- ''' ----------------------------------------------------------------------------------------------------
- ''' <summary>
- ''' The underliying <see cref="BackgroundWorker"/> instance.
- ''' </summary>
- ''' ----------------------------------------------------------------------------------------------------
- Private WithEvents bgw As BackgroundWorker
- ''' ----------------------------------------------------------------------------------------------------
- ''' <summary>
- ''' A <see cref="ManualResetEvent"/> that serves to handle synchronous operations (Run, Cancel).
- ''' </summary>
- ''' ----------------------------------------------------------------------------------------------------
- Private ReadOnly mreSync As ManualResetEvent
- ''' ----------------------------------------------------------------------------------------------------
- ''' <summary>
- ''' A <see cref="ManualResetEvent"/> that serves to handle asynchronous operations (RunAsync, Pause, Resume, CancelAsync).
- ''' </summary>
- ''' ----------------------------------------------------------------------------------------------------
- Private ReadOnly mreAsync As ManualResetEvent
- ''' ----------------------------------------------------------------------------------------------------
- ''' <summary>
- ''' Indicates whether <see cref="BackGroundworker"/> has been initiated in synchronous mode.
- ''' </summary>
- ''' ----------------------------------------------------------------------------------------------------
- Private isRunSync As Boolean = False
- ''' ----------------------------------------------------------------------------------------------------
- ''' <summary>
- ''' Indicates whether a synchronous cancellation operation is requested.
- ''' </summary>
- ''' ----------------------------------------------------------------------------------------------------
- Private isCancelSyncRequested As Boolean = False
- ''' ----------------------------------------------------------------------------------------------------
- ''' <summary>
- ''' Indicates whether a pause operation is requested.
- ''' </summary>
- ''' ----------------------------------------------------------------------------------------------------
- Private isPauseRequested As Boolean = False
- #End Region
- #Region " Properties "
- ''' ----------------------------------------------------------------------------------------------------
- ''' <summary>
- ''' Gets a value indicating whether this instance is running.
- ''' </summary>
- ''' ----------------------------------------------------------------------------------------------------
- ''' <value>
- ''' <see langword="True"/> if this instance is running, otherwise, <see langword="False"/>.
- ''' </value>
- ''' ----------------------------------------------------------------------------------------------------
- <EditorBrowsable(EditorBrowsableState.Always)>
- Public ReadOnly Property IsRunning As Boolean
- Get
- Return (Me.bgw IsNot Nothing) AndAlso (Me.bgw.IsBusy)
- End Get
- End Property
- ''' ----------------------------------------------------------------------------------------------------
- ''' <summary>
- ''' Gets a value indicating whether this instance is paused.
- ''' </summary>
- ''' ----------------------------------------------------------------------------------------------------
- ''' <value>
- ''' <see langword="True"/> if this instance is paused; otherwise, <see langword="False"/>.
- ''' </value>
- ''' ----------------------------------------------------------------------------------------------------
- <EditorBrowsable(EditorBrowsableState.Always)>
- Public ReadOnly Property IsPaused As Boolean
- Get
- Return (Me.bgw IsNot Nothing) AndAlso (Me.isPausedB)
- End Get
- End Property
- ''' ----------------------------------------------------------------------------------------------------
- ''' <summary>
- ''' (Backing Field)
- ''' A value indicating whether this instance is paused.
- ''' </summary>
- ''' ----------------------------------------------------------------------------------------------------
- Private isPausedB As Boolean = False
- ''' ----------------------------------------------------------------------------------------------------
- ''' <summary>
- ''' Gets a value indicating whether this instance is disposed.
- ''' </summary>
- ''' ----------------------------------------------------------------------------------------------------
- ''' <value>
- ''' <see langword="True"/> if this instance is disposed; otherwise, <see langword="False"/>.
- ''' </value>
- ''' ----------------------------------------------------------------------------------------------------
- <EditorBrowsable(EditorBrowsableState.Always)>
- Public ReadOnly Property IsDisposed As Boolean
- <DebuggerStepThrough>
- Get
- Return (Me.bgw Is Nothing)
- End Get
- End Property
- #End Region
- #Region " Constructors "
- ''' ----------------------------------------------------------------------------------------------------
- ''' <summary>
- ''' Initializes a new instance of the <see cref="Worker"/> class.
- ''' </summary>
- ''' ----------------------------------------------------------------------------------------------------
- <DebuggerNonUserCode>
- Public Sub New()
- Me.bgw = New BackgroundWorker()
- Me.mreSync = New ManualResetEvent(initialState:=False)
- Me.mreAsync = New ManualResetEvent(initialState:=True)
- End Sub
- #End Region
- #Region " Public Methods "
- ''' ----------------------------------------------------------------------------------------------------
- ''' <summary>
- ''' Starts this <see cref="Worker"/> and blocks the caller thread until the work is done.
- ''' </summary>
- ''' ----------------------------------------------------------------------------------------------------
- ''' <exception cref="InvalidOperationException">
- ''' This Worker is already running.
- ''' </exception>
- ''' ----------------------------------------------------------------------------------------------------
- <DebuggerStepThrough>
- Public Sub Run()
- If Not (Me.IsDisposed) AndAlso Not (Me.bgw.IsBusy) Then
- Me.isRunSync = True
- With Me.bgw
- .WorkerSupportsCancellation = False
- .WorkerReportsProgress = False
- .RunWorkerAsync()
- End With
- Me.mreSync.WaitOne()
- Else
- Throw New InvalidOperationException("This Worker is already running.")
- End If
- End Sub
- ''' ----------------------------------------------------------------------------------------------------
- ''' <summary>
- ''' Asynchonouslly starts this <see cref="Worker"/>.
- ''' </summary>
- ''' ----------------------------------------------------------------------------------------------------
- ''' <exception cref="InvalidOperationException">
- ''' This Worker is already running.
- ''' </exception>
- ''' ----------------------------------------------------------------------------------------------------
- <DebuggerStepThrough>
- Public Sub RunAsync()
- If Not (Me.IsDisposed) AndAlso Not (Me.bgw.IsBusy) Then
- With Me.bgw
- .WorkerSupportsCancellation = True
- .WorkerReportsProgress = True
- .RunWorkerAsync()
- End With
- Else
- Throw New InvalidOperationException("This Worker is already running.")
- End If
- End Sub
- ''' ----------------------------------------------------------------------------------------------------
- ''' <summary>
- ''' Pauses this <see cref="Worker"/>.
- ''' </summary>
- ''' ----------------------------------------------------------------------------------------------------
- ''' <exception cref="InvalidOperationException">
- ''' This Worker is not running.
- ''' </exception>
- ''' ----------------------------------------------------------------------------------------------------
- <DebuggerStepThrough>
- Public Sub Pause()
- If Not (Me.IsDisposed) AndAlso Not (Me.isPausedB) Then
- Me.isPauseRequested = True
- Me.isPausedB = True
- Me.mreAsync.Reset()
- Else
- Throw New InvalidOperationException("This Worker is not running.")
- End If
- End Sub
- ''' ----------------------------------------------------------------------------------------------------
- ''' <summary>
- ''' Resumes this <see cref="Worker"/>.
- ''' </summary>
- ''' ----------------------------------------------------------------------------------------------------
- ''' <exception cref="InvalidOperationException">
- ''' This Worker is not paused.
- ''' </exception>
- ''' ----------------------------------------------------------------------------------------------------
- <DebuggerStepThrough>
- Public Sub [Resume]()
- If Not (Me.IsDisposed) AndAlso (Me.isPausedB) Then
- Me.isPausedB = False
- Me.isPauseRequested = False
- Me.mreAsync.Set()
- Else
- Throw New InvalidOperationException("This Worker is not paused.")
- End If
- End Sub
- ''' ----------------------------------------------------------------------------------------------------
- ''' <summary>
- ''' Cancels this <see cref="Worker"/> and blocks the caller thread until the remaining work is done.
- ''' </summary>
- ''' ----------------------------------------------------------------------------------------------------
- ''' <exception cref="InvalidOperationException">
- ''' This Worker is not initialized.
- ''' </exception>
- ''' ----------------------------------------------------------------------------------------------------
- <DebuggerStepThrough>
- Public Sub Cancel()
- Me.isCancelSyncRequested = True
- Me.CancelAsync()
- Me.mreSync.WaitOne()
- Me.isCancelSyncRequested = False
- End Sub
- ''' ----------------------------------------------------------------------------------------------------
- ''' <summary>
- ''' Asynchronouslly cancels this <see cref="Worker"/>.
- ''' </summary>
- ''' ----------------------------------------------------------------------------------------------------
- ''' <exception cref="InvalidOperationException">
- ''' This Worker is not initialized.
- ''' </exception>
- ''' ----------------------------------------------------------------------------------------------------
- <DebuggerStepThrough>
- Public Sub CancelAsync()
- If Not (Me.IsDisposed) AndAlso Not (Me.bgw.CancellationPending) AndAlso (Me.bgw.IsBusy) Then
- Me.mreAsync.Set() ' Resume thread if it is paused.
- Me.bgw.CancelAsync()
- Else
- Throw New InvalidOperationException("This Worker is not initialized.")
- End If
- End Sub
- #End Region
- #Region " Private Methods "
- <DebuggerStepperBoundary>
- Private Sub DoSomething()
- Thread.Sleep(TimeSpan.FromSeconds(5))
- End Sub
- #End Region
- #Region " Event-Handlers "
- ''' ----------------------------------------------------------------------------------------------------
- ''' <summary>
- ''' Handles the <see cref="BackgroundWorker.DoWork"/> event of the <see cref="bgw"/> instance.
- ''' </summary>
- ''' ----------------------------------------------------------------------------------------------------
- ''' <param name="sender">
- ''' The source of the event.
- ''' </param>
- '''
- ''' <param name="e">
- ''' The <see cref="DoWorkEventArgs"/> instance containing the event data.
- ''' </param>
- ''' ----------------------------------------------------------------------------------------------------
- <DebuggerStepperBoundary>
- Private Sub DoWork(ByVal sender As Object, ByVal e As DoWorkEventArgs) _
- Handles bgw.DoWork
- Dim iterations As Integer = 5
- Dim progress As Integer
- Dim lock As Object = ""
- SyncLock lock
- For i As Integer = 0 To (iterations - 1)
- If (Me.bgw.CancellationPending) Then
- e.Cancel = True
- Exit For
- Else
- If Me.isPauseRequested Then ' Pause this thread right here.
- Me.mreAsync.WaitOne(Timeout.Infinite)
- End If
- Me.DoSomething()
- If Me.bgw.WorkerReportsProgress Then
- progress = ((i + 1) * (100 \ iterations))
- Me.bgw.ReportProgress(progress)
- End If
- End If
- Next i
- End SyncLock
- If (Me.bgw.WorkerReportsProgress) AndAlso Not (Me.bgw.CancellationPending) AndAlso (progress < 100) Then
- Me.bgw.ReportProgress(100)
- End If
- If (Me.isRunSync) OrElse (Me.isCancelSyncRequested) Then
- Me.mreSync.Set()
- End If
- End Sub
- ''' ----------------------------------------------------------------------------------------------------
- ''' <summary>
- ''' Handles the <see cref="BackgroundWorker.ProgressChanged"/> event of the <see cref="bgw"/> instance.
- ''' </summary>
- ''' ----------------------------------------------------------------------------------------------------
- ''' <param name="sender">
- ''' The source of the event.
- ''' </param>
- '''
- ''' <param name="e">
- ''' The <see cref="ProgressChangedEventArgs"/> instance containing the event data.
- ''' </param>
- ''' ----------------------------------------------------------------------------------------------------
- <DebuggerStepperBoundary>
- Private Sub ProgressChanged(ByVal sender As Object, ByVal e As ProgressChangedEventArgs) _
- Handles bgw.ProgressChanged
- Debug.WriteLine(String.Format("Work Progress: {0:00.00}%", e.ProgressPercentage))
- End Sub
- ''' ----------------------------------------------------------------------------------------------------
- ''' <summary>
- ''' Handles the <see cref="BackgroundWorker.RunWorkerCompleted"/> event of the <see cref="bgw"/> instance.
- ''' </summary>
- ''' ----------------------------------------------------------------------------------------------------
- ''' <param name="sender">
- ''' The source of the event.
- ''' </param>
- '''
- ''' <param name="e">
- ''' The <see cref="RunWorkerCompletedEventArgs"/> instance containing the event data.
- ''' </param>
- ''' ----------------------------------------------------------------------------------------------------
- <DebuggerStepperBoundary>
- Private Sub Bgw_RunWorkerCompleted(ByVal sender As Object, ByVal e As RunWorkerCompletedEventArgs) _
- Handles bgw.RunWorkerCompleted
- If (e.Cancelled) Then
- Debug.WriteLine("Work state: Cancelled")
- ElseIf (e.Error IsNot Nothing) Then
- Debug.WriteLine("Work state: Error")
- Else
- Debug.WriteLine("Work state: Success")
- End If
- Me.Dispose()
- End Sub
- #End Region
- #Region " IDisposable Implementation "
- ''' ----------------------------------------------------------------------------------------------------
- ''' <summary>
- ''' To detect redundant calls when disposing.
- ''' </summary>
- ''' ----------------------------------------------------------------------------------------------------
- Private isDisposedB As Boolean
- ''' ----------------------------------------------------------------------------------------------------
- ''' <summary>
- ''' Releases all the resources used by this instance.
- ''' </summary>
- ''' ----------------------------------------------------------------------------------------------------
- <DebuggerStepThrough>
- Public Sub Dispose() Implements IDisposable.Dispose
- Me.Dispose(isDisposing:=True)
- GC.SuppressFinalize(obj:=Me)
- End Sub
- ''' ----------------------------------------------------------------------------------------------------
- ''' <summary>
- ''' Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
- ''' <para></para>
- ''' Releases unmanaged and, optionally, managed resources.
- ''' </summary>
- ''' ----------------------------------------------------------------------------------------------------
- ''' <param name="isDisposing">
- ''' <see langword="True"/> to release both managed and unmanaged resources;
- ''' <see langword="False"/> to release only unmanaged resources.
- ''' </param>
- ''' ----------------------------------------------------------------------------------------------------
- <DebuggerStepThrough>
- Private Sub Dispose(ByVal isDisposing As Boolean)
- If (Not Me.isDisposedB) AndAlso (isDisposing) Then
- Me.bgw.Dispose()
- Me.bgw = Nothing
- With Me.mreSync
- .SafeWaitHandle.Close()
- .SafeWaitHandle.Dispose()
- .Close()
- .Dispose()
- End With
- With Me.mreAsync
- .SafeWaitHandle.Close()
- .SafeWaitHandle.Dispose()
- .Close()
- .Dispose()
- End With
- Me.isPausedB = False
- Me.isRunSync = False
- End If
- Me.isDisposedB = True
- End Sub
- #End Region
- #Region " Hidden Base Members "
- ''' ----------------------------------------------------------------------------------------------------
- ''' <summary>
- ''' Serves as a hash function for a particular type.
- ''' </summary>
- ''' ----------------------------------------------------------------------------------------------------
- ''' <returns>
- ''' A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table.
- ''' </returns>
- ''' ----------------------------------------------------------------------------------------------------
- <DebuggerNonUserCode>
- <EditorBrowsable(EditorBrowsableState.Never)>
- Public Shadows Function GetHashCode() As Integer
- Return MyBase.GetHashCode
- End Function
- ''' ----------------------------------------------------------------------------------------------------
- ''' <summary>
- ''' Gets the <see cref="System.Type"/> of the current instance.
- ''' </summary>
- ''' ----------------------------------------------------------------------------------------------------
- ''' <returns>
- ''' The exact runtime type of the current instance.
- ''' </returns>
- ''' ----------------------------------------------------------------------------------------------------
- <EditorBrowsable(EditorBrowsableState.Never)>
- <DebuggerNonUserCode>
- Public Shadows Function [GetType]() As Type
- Return MyBase.GetType
- End Function
- ''' ----------------------------------------------------------------------------------------------------
- ''' <summary>
- ''' Determines whether the specified <see cref="Object"/> is equal to this instance.
- ''' </summary>
- ''' ----------------------------------------------------------------------------------------------------
- ''' <param name="obj">
- ''' Another object to compare to.
- ''' </param>
- ''' ----------------------------------------------------------------------------------------------------
- ''' <returns>
- ''' <see langword="True"/> if the specified <see cref="Object"/> is equal to this instance; otherwise, <see langword="False"/>.
- ''' </returns>
- ''' ----------------------------------------------------------------------------------------------------
- <EditorBrowsable(EditorBrowsableState.Never)>
- <DebuggerNonUserCode>
- Public Shadows Function Equals(ByVal obj As Object) As Boolean
- Return MyBase.Equals(obj)
- End Function
- ''' ----------------------------------------------------------------------------------------------------
- ''' <summary>
- ''' Returns a string that represents the current object.
- ''' </summary>
- ''' ----------------------------------------------------------------------------------------------------
- ''' <returns>
- ''' A string that represents the current object.
- ''' </returns>
- ''' ----------------------------------------------------------------------------------------------------
- <EditorBrowsable(EditorBrowsableState.Never)>
- <DebuggerNonUserCode>
- Public Shadows Function ToString() As String
- Return MyBase.ToString
- End Function
- #End Region
- End Class
- #End Region
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement