在不冻结UI的情况下将150,000条记录添加到列表视图 [英] Adding 150,000 records to a listview without freezing UI

查看:54
本文介绍了在不冻结UI的情况下将150,000条记录添加到列表视图的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个listview循环,该循环向我的listview中添加了150,000个项目.为了进行测试,我将此代码移到了具有委托的后台工作人员,但它仍然冻结UI.我试图找到一种解决方案,以便在我在应用程序中执行其他操作时可以在后台添加这些项目.你们推荐什么解决方案?

I have a listview loop that is adding 150,000 items to my listview. For testing purposes I moved this code to a background worker with delegates, but it still freezes up the UI. I am trying to find a solution so that it can add these items in the background while I do other stuff in the app. What solutions do you guys recommend?

这就是我正在使用的

   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 " & 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

推荐答案

尝试一下,这是您需要的一个很好的示例...我还有一个进度条,显示进度等,请参见示例图像这是附加的.另外,我没有看到执行此操作所需的任何委托,我的委托是必需的.原因是您要向UI线程上的控件添加项目,为了添加项目,我们需要知道是否需要Invoke,如果需要,则调用它,否则我们将项目添加到控件中...我也做了线程处于睡眠状态,因此可能需要休息一下;这也 防止了用户界面想要在这里和那里锁定 ,现在它可以响应 不冻结 .

Give this a try, it's a great example for what you would need... I also had a progress bar that shows the progress and such, see example image that is attached. Also I wasn't seeing any delegate that you need to perform such operation, mine has one that will be required. The reason is you are adding items to a control on the UI thread, in order to add items we need to know if an Invoke is required, if so we invoke otherwise we add the item to the control... Also I made the thread sleep, so it can take a break; this also prevents the UI from wanting to lock up here and there, now it's responsive with NO FREEZING.

 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 " & 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 & " 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

实际屏幕截图...

这篇关于在不冻结UI的情况下将150,000条记录添加到列表视图的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆