Imports System.Threading
Public NotInheritable Class Work : Implements IDisposable
#Region " Private Fields "
<EditorBrowsable(EditorBrowsableState.Never)>
Friend WithEvents Bgw As BackgroundWorker
Private ReadOnly mreSync As ManualResetEvent
Private ReadOnly mreAsync As ManualResetEvent
Private isRunSync As Boolean = False
Private isCancelSyncRequested As Boolean = False
Private isPauseRequested As Boolean = False
#End Region
#Region " Properties "
<EditorBrowsable(EditorBrowsableState.Always)>
Public ReadOnly Property IsRunning As Boolean
Get
Return (Me.Bgw IsNot Nothing) AndAlso Not (Me.isPausedB)
End Get
End Property
<EditorBrowsable(EditorBrowsableState.Always)>
Public ReadOnly Property IsPaused As Boolean
Get
Return (Me.Bgw IsNot Nothing) AndAlso (Me.isPausedB)
End Get
End Property
Private isPausedB As Boolean = False
Public ReadOnly Property IsDisposed As Boolean
<DebuggerStepThrough>
Get
Return (Me.Bgw Is Nothing)
End Get
End Property
#End Region
#Region " Constructors "
<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 "
<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("BackGroundWorker is already running.")
End If
End Sub
<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("BackGroundWorker is already running.")
End If
End Sub
<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("BackGroundWorker is not running.")
End If
End Sub
<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("BackGroundWorker is not paused.")
End If
End Sub
<DebuggerStepThrough>
Public Sub Cancel(Optional ByVal throwOnError As Boolean = False)
Me.isCancelSyncRequested = True
Me.CancelAsync()
Me.mreSync.WaitOne()
Me.isCancelSyncRequested = False
End Sub
<DebuggerStepThrough>
Public Sub CancelAsync(Optional ByVal throwOnError As Boolean = False)
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("BackGroundWorker is not initialized.")
End If
End Sub
#End Region
#Region " Private Methods "
<DebuggerStepThrough>
Private Function AddLvItem(ByVal src As ListView, ByVal dst As ListView, ByVal index As Integer) As ListViewItem
Dim result As ListViewItem = Nothing
If (dst.InvokeRequired) Then
dst.Invoke(
Sub()
Try
result = dst.Items.Add(src.Items(index).Text)
Catch ex As Exception
Debug.
WriteLine(String.
Format("Woker exception occured: {0}", ex.
Message)) End Try
End Sub)
Else
Try
result = dst.Items.Add(src.Items(index).Text)
Catch ex As Exception
Debug.
WriteLine(String.
Format("Woker exception occured: {0}", ex.
Message)) End Try
End If
Return result
End Function
#End Region
#Region " Event-Handlers "
<DebuggerStepperBoundary>
Private Sub MyWorker_DoWork(ByVal sender As Object, ByVal e As DoWorkEventArgs) _
Handles Bgw.DoWork
Dim lock As Object = ""
SyncLock lock
Dim lv1 As ListView = WindowsApplication1.Form1.ListView1
Dim lv2 As ListView = WindowsApplication1.Form1.ListView2
Dim max As Integer = lv2.Items.Count
Dim itemIndex As Integer = -1
For i As Integer = 0 To (max - 1)
If (Me.Bgw.CancellationPending) Then
e.Cancel = True
Exit For
Else
If Me.isPauseRequested Then ' Pause this thread.
Me.mreAsync.WaitOne(Timeout.Infinite)
End If
Dim lvi As ListViewItem = Me.AddLvItem(src:=lv2, dst:=lv1, index:=Interlocked.Increment(itemIndex))
If (lvi IsNot Nothing) Then
Debug.
WriteLine(String.
Format("ListViewItem Text: {0}", lvi.
Text)) End If
If Me.Bgw.WorkerReportsProgress Then
Me.Bgw.ReportProgress((i + 1) * (100 \ max))
End If
Thread.Sleep(TimeSpan.FromSeconds(1))
End If
Next i
End SyncLock
If (Me.Bgw.WorkerReportsProgress) AndAlso Not (Me.Bgw.CancellationPending) Then
Me.Bgw.ReportProgress(100)
End If
If (Me.isRunSync) OrElse (Me.isCancelSyncRequested) Then
Me.mreSync.Set()
End If
End Sub
<DebuggerStepperBoundary>
Private Sub Bgw_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
<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 "
Private isDisposedB As Boolean
<DebuggerStepThrough>
Public Sub Dispose() Implements IDisposable.Dispose
Me.Dispose(isDisposing:=True)
GC.SuppressFinalize(obj:=Me)
End Sub
<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
End If
Me.isDisposedB = True
End Sub
#End Region
#Region " Hidden Methods "
<EditorBrowsable(EditorBrowsableState.Never)>
<DebuggerNonUserCode>
Public Shadows Function GetHashCode() As Integer
Return MyBase.GetHashCode
End Function
<EditorBrowsable(EditorBrowsableState.Never)>
<DebuggerNonUserCode>
Public Shadows Function [GetType]() As Type
Return MyBase.GetType
End Function
<EditorBrowsable(EditorBrowsableState.Never)>
<DebuggerNonUserCode>
Public Shadows Function Equals(ByVal obj As Object) As Boolean
Return MyBase.Equals(obj)
End Function
<EditorBrowsable(EditorBrowsableState.Never)>
<DebuggerNonUserCode>
Public Shadows Function ToString() As String
Return MyBase.ToString
End Function
#End Region
End Class