#vb.net #winforms #backgroundworker
#vb.net #winforms #backgroundworker
Вопрос:
У меня есть цикл listview, который добавляет 150 000 элементов в мой listview. В целях тестирования я перенес этот код в фоновый рабочий с делегатами, но он по-прежнему зависает в пользовательском интерфейсе. Я пытаюсь найти решение, чтобы оно могло добавлять эти элементы в фоновом режиме, пока я делаю другие вещи в приложении. Какие решения вы, ребята, рекомендуете?
это то, что я использую
Public Class Form1
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
ListView1.Clear()
ListView1.BeginUpdate()
bw.WorkerReportsProgress = True
bw.RunWorkerAsync()
End Sub
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
If bw.IsBusy Then bw.CancelAsync()
End Sub
Private Sub bw_DoWork(ByVal sender As Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles bw.DoWork
For x = 1 To 125000
Dim lvi As New ListViewItem("Item " amp; x)
If bw.CancellationPending Then
e.Cancel = True
Exit For
Else
bw.ReportProgress(0, lvi)
End If
Next
End Sub
Private Sub bw_ProgressChanged(ByVal sender As Object, ByVal e As System.ComponentModel.ProgressChangedEventArgs) Handles bw.ProgressChanged
Try
Dim lvi As ListViewItem = DirectCast(e.UserState, ListViewItem)
Me.ListView1.Items.Add(lvi)
Catch ex As Exception
Throw New Exception(ex.Message)
End Try
End Sub
Private Sub bw_RunWorkerCompleted(ByVal sender As Object, ByVal e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles bw.RunWorkerCompleted
ListView1.EndUpdate()
If Not e.Cancelled Then
Debug.Print("Done")
Else
Debug.Print("Cancelled")
End If
End Sub
End Class
Комментарии:
1. 150 кб — это много для пользовательского интерфейса, даже для не веб-приложения.
Ответ №1:
Попробуйте, это отличный пример того, что вам нужно… У меня также был индикатор выполнения, который показывает прогресс и тому подобное, см. Пример изображения, которое прилагается. Также я не видел ни одного делегата, который вам нужен для выполнения такой операции, у меня есть тот, который потребуется. Причина в том, что вы добавляете элементы в элемент управления в потоке пользовательского интерфейса, для добавления элементов нам нужно знать, требуется ли an Invoke
, если это так, мы вызываем, иначе мы добавляем элемент в элемент управления… Также я перевел поток в спящий режим, чтобы он мог сделать перерыв; это также предотвращает блокировку пользовательского интерфейса здесь и там, теперь он реагирует без ЗАВИСАНИЯ.
Option Strict On
Option Explicit On
Public Class Form1
Delegate Sub SetListItem(ByVal lstItem As ListViewItem) 'Your delegate..
'Start the process...
Private Sub btnStartProcess_Click(sender As Object, e As EventArgs) Handles btnStartProcess.Click
lvItems.Clear()
bwList.RunWorkerAsync()
End Sub
Private Sub AddListItem(ByVal lstItem As ListViewItem)
If Me.lvItems.InvokeRequired Then 'Invoke if required...
Dim d As New SetListItem(AddressOf AddListItem) 'Your delegate...
Me.Invoke(d, New Object() {lstItem})
Else 'Otherwise, no invoke required...
Me.lvItems.Items.Add(lstItem)
End If
End Sub
Private Sub bwList_DoWork(sender As Object, e As System.ComponentModel.DoWorkEventArgs) Handles bwList.DoWork
Dim intCount As Integer = CInt(txtCount.Text)
Dim dblPercent As Integer = 100
Dim intComplete As Integer = 0
Dim li As ListViewItem = Nothing
For i As Integer = 1 To CInt(txtCount.Text)
If Not (bwList.CancellationPending) Then
li = New ListViewItem
li.Text = "Item " amp; i.ToString
AddListItem(li)
Threading.Thread.Sleep(1) 'Give the thread a very..very short break...
ElseIf (bwList.CancellationPending) Then
e.Cancel = True
Exit For
End If
intComplete = CInt(CSng(i) / CSng(intCount) * 100)
If intComplete < dblPercent Then
bwList.ReportProgress(intComplete)
End If
If li IsNot Nothing Then
li = Nothing
End If
Next
End Sub
Private Sub bwList_ProgressChanged(sender As Object, e As System.ComponentModel.ProgressChangedEventArgs) Handles bwList.ProgressChanged
pbList.Value = e.ProgressPercentage
End Sub
Private Sub bwList_RunWorkerCompleted(sender As Object, e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles bwList.RunWorkerCompleted
If pbList.Value < 100 Then pbList.Value = 100
MessageBox.Show(lvItems.Items.Count.ToString amp; " items were added!")
End Sub
Private Sub btnStopWork_Click(sender As Object, e As EventArgs) Handles btnStopWork.Click
bwList.CancelAsync()
End Sub
Private Sub btnRestart_Click(sender As Object, e As EventArgs) Handles btnRestart.Click
pbList.Value = 0
lvItems.Items.Clear()
txtCount.Text = String.Empty
End Sub
End Class
Скриншот в действии…
Комментарии:
1. Могут ли быть проблемы с памятью?
2. Я запускал Ants profiler и не видел ничего подобного. Почему это должно быть?
3. @SysDragon отличный момент. Это может быть возможно, так как это довольно много элементов для ListView. Я не уверен насчет компьютера операционной системы, но у меня есть много, которые не были затронуты. Я даже разделил элементы на куски, и это все равно не имело плохого эффекта и было так же быстро, как если бы я его не разделял.
4. Хорошее решение, это отлично подходит для работы с большими списками данных