如何使用多线程将文本文件中的项目加载到列表框中

How to load items from text file into listbox using multiple thread

我目前正在使用以下代码将文本文件项加载到我的一个应用程序的列表框中,它可以工作,但该文本文件的大小超过 10mb。所以应用程序在将项目加载到列表框时卡住了几秒钟。

一旦项目被加载,它就可以正常工作。那么有什么办法可以减少加载时间和防止应用程序挂起。

Public Sub loadfiles()
    Dim systemdrv As String = Mid(Environment.GetFolderPath(Environment.SpecialFolder.System), 1, 3)
    Dim r As IO.StreamReader
    r = New IO.StreamReader(systemdrv + "temp\test.txt")
    While (r.Peek() > -1)
        ListBox2.Items.Add(r.ReadLine)
    End While
    r.Close()
End Sub

我读到一些是说使用多线程可以解决问题。所以我尝试了一些东西但每次都失败了...

您可以同时使用线程或后台工作程序

尽管您需要编辑代码,但无法从另一个线程更新 UI,因此请将您读取的行保存到数组中或使用 File.ReadAllLines(path) 方法这将 return 直接一个数组,而不是直接将它们添加到列表框中。

我将使用后台工作者,因为它会在完成工作时引发事件,并且您需要知道何时可以将项目添加到列表框,因此:

添加一个后台工作者并使用其事件DoWork()RunWorkerCompleted()分别读取文本行并将数组放入列表框:

Dim readText() as String
Private Sub BackgroundWorker1_DoWork(ByVal sender As System.Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork
    Dim systemdrv As String = Mid(Environment.GetFolderPath(Environment.SpecialFolder.System), 1, 3)
    readText = IO.File.ReadAllLines(systemdrv + "temp\test.txt")
End Sub

Private Sub BackgroundWorker1_RunWorkerCompleted(ByVal sender As System.Object, ByVal e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles BackgroundWorker1.RunWorkerCompleted
    ListBox2.Items.AddRange(readText)
End Sub

现在从您想开始阅读文件的地方添加 (form_load, button_click):

BackgroundWorker1.RunWorkerAsync()

对单个文件的多次读取并不是真正的解决方案,在大多数情况下,加载时间不会有任何减少,因为对存储的访问实际上是顺序的。 但是,您可以简单地用 BackgroundWorker or in a Action.

来防止应用程序挂起

请注意,在 Windows Form 中,只有创建 Form 的主线程才能修改 Form 中的任何组件,因此您需要将结果存储在一个附加变量中或将每个修改操作包装在一个代表。如果你想保持加载效果(对于给客户端一个工作效果很有用)你可以使用 Delegate 包装在 BackgroundWorker 中。

Private Sub BackgroundWorker1_DoWork(ByVal sender As System.Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork
    Dim systemdrv As String = Mid(Environment.GetFolderPath(Environment.SpecialFolder.System), 1, 3)
    Dim r As IO.StreamReader
    r = New IO.StreamReader(systemdrv + "temp\test.txt")
    While (r.Peek() > -1)
        Dim line As String = r.ReadLine
        If ListBox2.InvokeRequired Then
            Listbox2.Invoke(Sub() ListBox2.Items.Add(line))
        Else
            ListBox2.Items.Add(line)
    End While
    r.Close()
End Sub