我一直在努力寻找一种解决方案,以解决如何将BackgroundWorker正确地集成到我的Feature中,并能够正确显示流程开发,流程停止,报告。
在我的问题中,我将尽最大努力拆分几乎所有代码,以便您可以更轻松地为我提供帮助,并引起您的注意,以便我可以正确地包含最小值(tb_min_Nr)而不是MinProgess = 0,如下所示以及最大值(tb_max_nr)而不是MaxProgress = 100。
这是我的代码
Public Class FormMain
Public MasterMandantConnectionString As String
Private fileWorker As BackgroundWorker(Of String(), String, List(Of FileData))
Private files As String()
Public Sub New()
' This call is required by the Windows Form Designer.
InitializeComponent()
fileWorker = New BackgroundWorker(Of String(), String, List(Of FileData))
AddHandler fileWorker.DoWork, AddressOf fileWorker_DoWorkHandler
AddHandler fileWorker.ProgressChanged, AddressOf fileWorker_ProgressChangedHandler
AddHandler fileWorker.RunWorkerCompleted, AddressOf fileWorker_RunWorkerCompletedHandler
End Sub
Public Sub fileWorker_DoWorkHandler(ByVal sender As Object, ByVal e As DoWorkEventArgs(Of String(), List(Of FileData)))
Dim progress As Integer = 0
e.Result = New List(Of FileData)(e.Argument.Length)
For Each file As String In e.Argument
If fileWorker.CancellationPending Then
e.Cancel = True
Return
End If
fileWorker.ReportProgress(progress, file)
Thread.Sleep(50)
MasterMandantConnectionString = "Data Source=sql.com;Initial Catalog=Master;User ID=sa"
For Mob_Nr = tb_Min_Nr.Value To tb_Max_Nr.Value
Cdrs = Put_CDRs_To_FakturaPos(MasterMandantConnectionString:=MasterMandantConnectionString,
Startdate:=dtp_Start.Value,
EndDate:=dtp_End.Value,
Mob_Nr:=Mob_Nr)
For Each cdr In Cdrs
e.Result.Add(New FileData(cdr))
Next
Next
progress += 2
Next
fileWorker.ReportProgress(progress, String.Empty)
End Sub
Public Sub fileWorker_ProgressChangedHandler _
(ByVal sender As Object, ByVal e As ProgressChangedEventArgs(Of String))
labelProgress.Text = e.UserState
progressBar.Value = e.ProgressPercentage
End Sub
Public Sub fileWorker_RunWorkerCompletedHandler(ByVal sender As Object, ByVal e As RunWorkerCompletedEventArgs(Of List(Of FileData)))
If e.Cancelled Then
labelProgress.Text = "Cancelled"
progressBar.Value = 0
Else
labelProgress.Text = "Done!"
End If
listBox.DataSource = e.Result
listBox.Enabled = True
buttonStart.Enabled = True
buttonCancel.Enabled = False
progressBar.Enabled = False
AcceptButton = buttonStart
End Sub
Dim Cdrs As List(Of String)
Private Sub buttonStart_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles buttonStart.Click
buttonCancel.Enabled = True
AcceptButton = buttonCancel
buttonStart.Enabled = False
listBox.DataSource = Nothing
listBox.Enabled = False
files = Enumerable.Range(tb_Min_Nr.Value, tb_Max_Nr.Value).Select(Function(x) x.ToString).ToArray()
fileWorker.RunWorkerAsync(files) 'my assumption is that in this part I am wrong, here I should pass min and max in order for the process to go from the minimum entered value to the maximum, it takes the current array list with me, and executes the process incorrectly.
End Sub
Private Sub buttonCancel_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles buttonCancel.Click
fileWorker.CancelAsync()
End Sub
End Class
Public Class BackgroundWorker(Of TArgument, TProgress, TResult)
Public Const MinProgress As Int32 = 0
Public Const MaxProgress As Int32 = 100
Public Event DoWork As EventHandler(Of DoWorkEventArgs(Of TArgument, TResult))
Public Event ProgressChanged As EventHandler(Of ProgressChangedEventArgs(Of TProgress))
Public Event RunWorkerCompleted As EventHandler(Of RunWorkerCompletedEventArgs(Of TResult))
Private asyncOperation As AsyncOperation = Nothing
Private ReadOnly threadStart As BasicDelegate
Private ReadOnly operationCompleted As SendOrPostCallback
Private ReadOnly progressReporterDelegate As SendOrPostCallback
Private _CancellationPending As Boolean
Private _IsBusy As Boolean
Private _WorkerReportsProgress As Boolean
Private _WorkerSupportsCancellation As Boolean
Public Sub New()
threadStart = AddressOf WorkerThreadStart
operationCompleted = AddressOf AsyncOperationCompleted
progressReporterDelegate = AddressOf ProgressReporter
WorkerReportsProgress = True
WorkerSupportsCancellation = True
End Sub
Public Property CancellationPending() As Boolean
Get
Return _CancellationPending
End Get
Private Set(ByVal value As Boolean)
_CancellationPending = value
End Set
End Property
Public Property IsBusy() As Boolean
Get
Return _IsBusy
End Get
Private Set(ByVal value As Boolean)
_IsBusy = value
End Set
End Property
Public Property WorkerReportsProgress() As Boolean
Get
Return _WorkerReportsProgress
End Get
Set(ByVal value As Boolean)
_WorkerReportsProgress = value
End Set
End Property
Public Property WorkerSupportsCancellation() As Boolean
Get
Return _WorkerSupportsCancellation
End Get
Set(ByVal value As Boolean)
_WorkerSupportsCancellation = value
End Set
End Property
Private Sub AsyncOperationCompleted(ByVal state As Object)
IsBusy = False
CancellationPending = False
OnRunWorkerCompleted(CType(state, RunWorkerCompletedEventArgs(Of TResult)))
End Sub
Public Function CancelAsync() As Boolean
If Not WorkerSupportsCancellation Then
Return False
End If
CancellationPending = True
Return True
End Function
Protected Overridable Sub OnDoWork(ByVal e As DoWorkEventArgs(Of TArgument, TResult))
RaiseEvent DoWork(Me, e)
End Sub
Protected Overridable Sub OnProgressChanged(ByVal e As ProgressChangedEventArgs(Of TProgress))
RaiseEvent ProgressChanged(Me, e)
End Sub
Protected Overridable Sub OnRunWorkerCompleted(ByVal e As RunWorkerCompletedEventArgs(Of TResult))
RaiseEvent RunWorkerCompleted(Me, e)
End Sub
Private Sub ProgressReporter(ByVal state As Object)
OnProgressChanged(CType(state, ProgressChangedEventArgs(Of TProgress)))
End Sub
Public Function ReportProgress(ByVal percentProgress As Int32) As Boolean
Return ReportProgress(percentProgress, CType(Nothing, TProgress))
End Function
Public Function ReportProgress(ByVal percentProgress As Int32, ByVal userState As TProgress) As Boolean
If Not WorkerReportsProgress Then
Return False
End If
If percentProgress < MinProgress Then
percentProgress = MinProgress
ElseIf percentProgress > MaxProgress Then
percentProgress = MaxProgress
End If
Dim args As ProgressChangedEventArgs(Of TProgress) =
New ProgressChangedEventArgs(Of TProgress)(percentProgress, userState)
If Not asyncOperation Is Nothing Then
asyncOperation.Post(progressReporterDelegate, args)
Else
progressReporterDelegate(args)
End If
Return True
End Function
Public Function RunWorkerAsync() As Boolean
Return RunWorkerAsync(CType(Nothing, TArgument))
End Function
Public Function RunWorkerAsync(ByVal argument As TArgument) As Boolean
If IsBusy Then
Return False
End If
IsBusy = True
CancellationPending = False
asyncOperation = AsyncOperationManager.CreateOperation(argument)
threadStart.BeginInvoke(Nothing, Nothing)
Return True
End Function
Private Sub WorkerThreadStart()
Dim workerResult As TResult = CType(Nothing, TResult)
Dim err As Exception = Nothing
Dim cancelled As Boolean = False
Try
Dim doWorkArgs As DoWorkEventArgs(Of TArgument, TResult) =
New DoWorkEventArgs(Of TArgument, TResult)(CType(asyncOperation.UserSuppliedState, TArgument))
OnDoWork(doWorkArgs)
If doWorkArgs.Cancel Then
cancelled = True
Else
workerResult = doWorkArgs.Result
End If
Catch exception As Exception
err = exception
End Try
Dim e As RunWorkerCompletedEventArgs(Of TResult) = New RunWorkerCompletedEventArgs(Of TResult)(workerResult, err, cancelled)
asyncOperation.PostOperationCompleted(operationCompleted, e)
End Sub
End Class
我的问题是,我可以在backgroundorker类中转发MinProgres和MaxpPogress值吗?
如果您有一些要包含在进度报告中的信息,则可以为其创建一个类:
Private Class ProgressReportData
Property CurrentMin As Integer
Property CurrentMax As Integer
' Other properties as needed.
End Class
然后像这样使用它来填充e.UserState
对象:
e.UserState
并处理事件:
Dim progReport As New ProgressReportData With {.CurrentMin = x, .CurrentMax = y}
worker.ReportProgress(percentSoFar, progReport)