Что вам нужно сделать, это отделить части пользовательского интерфейса (такие как ListViews, MessageBoxes и т. Д. c.) От фонового работника.
- Способ передачи данных в BGW заключается в передать объект в
.Argument
. - Чтобы извлечь из него данные во время его работы, используйте событие ReportProgress и передайте все, что вы хотите, в
.UserState
объект. - Чтобы получить данные из него после его завершения, используйте свойство
.Result
.
Мы не будем использовать какой-либо результат в этом случае, но я установлю его как логическое значение, если вы хотите изменить его. Итак, давайте создадим классы для ввода и вывода данных ...
Private Class BgwArgs
Property StartDate As DateTime
Property EndDate As DateTime
Property MinNr As Integer
Property MaxNr As Integer
Property ConnStr As String
End Class
Private Class ProgressReportData
Property ErrorMessages As List(Of String)
End Class
Первоначальная настройка BGW выглядит следующим образом:
Private Sub Btn_OK_Click(sender As Object, e As EventArgs) Handles Btn_OK.Click
ListView1.Items.Clear()
ResetCounter()
Dim args As New BgwArgs With {.StartDate = dtp_Start.Value,
.EndDate = dtp_End.Value,
.MinNr = CInt(tb_Min_Nr.Value),
.MaxNr = CInt(tb_Max_Nr.Value),
.ConnStr = "your connection string"}
ProgressBar1.Minimum = 0
ProgressBar1.Maximum = 100
BackgroundWorker1.WorkerReportsProgress = True
BackgroundWorker1.WorkerSupportsCancellation = True
BackgroundWorker1.RunWorkerAsync(args)
End Sub
, а затем все части:
Private Sub BackgroundWorker1_DoWork(sender As Object, e As DoWorkEventArgs) Handles BackgroundWorker1.DoWork
Dim worker As BackgroundWorker = TryCast(sender, BackgroundWorker)
e.Result = TestPut_All_CDRs_To_FakturaPos(worker, e)
End Sub
Private Function TestPut_All_CDRs_To_FakturaPos(worker As BackgroundWorker, e As DoWorkEventArgs) As Boolean
Dim importedInfo As New List(Of String)
Dim args = CType(e.Argument, BgwArgs)
Dim masterMandantConnectionString = args.ConnStr
Dim startDate = args.StartDate
Dim endDate = args.EndDate
Dim min_Nr = args.MinNr
Dim max_Nr = args.MaxNr
Dim n As Integer = 0
Dim totalMobs = max_Nr - min_Nr + 1
For mob_Nr = min_Nr To max_Nr
n += 1
If worker.CancellationPending Then
e.Cancel = True
Else
Dim mobCdrs = TestPut_Mob_CDRs_To_FakturaPos(MasterMandantConnectionString:=masterMandantConnectionString,
StartDate:=startDate,
EndDate:=endDate,
Mob_Nr:=mob_Nr)
Dim pct = n * 100 \ totalMobs
Dim progReport As New ProgressReportData With {.ErrorMessages = mobCdrs.Where(Function(m) Not String.IsNullOrEmpty(m)).ToList()}
worker.ReportProgress(pct, progReport)
End If
Next
Return True
End Function
Private Sub backgroundWorker1_ProgressChanged(ByVal sender As Object, ByVal e As ProgressChangedEventArgs) Handles BackgroundWorker1.ProgressChanged
Dim progData = CType(e.UserState, ProgressReportData)
ProgressBar1.Value = e.ProgressPercentage
If progData.ErrorMessages IsNot Nothing Then
For Each m In progData.ErrorMessages
ListView1.Items.Add(m)
Next
End If
End Sub
Private Sub backgroundWorker1_RunWorkerCompleted(ByVal sender As Object, ByVal e As RunWorkerCompletedEventArgs) Handles BackgroundWorker1.RunWorkerCompleted
If (e.Error IsNot Nothing) Then
ProgressBar1.ForeColor = Color.Red
MessageBox.Show(e.Error.Message, "Exception", MessageBoxButtons.OK, MessageBoxIcon.Error)
ElseIf e.Cancelled Then
' Next, handle the case where the user cancelled the operation.
' Note that due to a race condition in the DoWork event handler, the Cancelled flag may not have been set, even though CancelAsync was called.
ProgressBar1.ForeColor = Color.HotPink
Else
ProgressBar1.ForeColor = Color.LawnGreen
ListView1.Items.Insert(0, GetImportInfo(), 0)
labelInfo.Text = "Test successfully completed."
' We could use e.Result here if something useful was returned in it.
' Dim flag = CType(e.Result, Boolean)
End If
End Sub
Процент прогресса вычисляется в l oop, поскольку это простой способ сделать это.
Я не смог проверить это, но, надеюсь, там достаточно для вас чтобы получить рабочий код.
(я использую Option Infer On и Option Strict On.)