请参阅以下代码。这基本上只是我的一个实验,所以我可以在Visual Basic中解决各种问题,即如何使用后台工作程序,读取文件等。
我有一个100,000行的小文件,以及1,000,000行的大文件。
文件结构为“数据A |数据A-1”,新行,“数据A |数据A-2”等,一直向下。
我正在做的是让用户选择文件,然后将其填充到两个列表框中,以便能够看到数据正确读取。
以下代码在我的机器上大约需要22秒来读取小文件的完成情况,但是大文件需要8分半钟才能完成。对于较大的文件,我预计在3:30到4分钟之间的时间,基于行数。这个额外的时间来自哪里?我有什么办法可以摆脱它吗?
Option Strict On
Option Explicit On
Imports System.ComponentModel
Imports System.IO
Imports System.Text
Public Class frmMain
Dim WithEvents bwWorkerThread As BackgroundWorker = New BackgroundWorker
Dim strFilePath As String 'record user selected file path
Private Sub frmMain_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
bwWorkerThread.WorkerSupportsCancellation = True 'this thread can be stopped mid-process
bwWorkerThread.WorkerReportsProgress = True 'this thread gives updates on how it is doing
End Sub
'When you click "Start"
Private Sub btnStart_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnStart.Click
btnStart.Enabled = False 'disable start button, so user can't start it while it is still in progress
btnStop.Enabled = True 'enable stop button, so user can stop it only after it has begun
Dim ofdThreadTest As OpenFileDialog = New OpenFileDialog
ofdThreadTest.CheckFileExists = True 'don't process fake files...
ofdThreadTest.CheckPathExists = True '...or fake pathways
ofdThreadTest.ReadOnlyChecked = True 'only read, no writing
ofdThreadTest.ValidateNames = True 'don't process invalid names
ofdThreadTest.Filter = "Files (*.dat)|*.dat" 'only allow the user to select and open the appropriate files
If ofdThreadTest.ShowDialog() = DialogResult.OK Then 'only run if the user actually selects a file...
strFilePath = ofdThreadTest.FileName '...store the file name and pathway to a string...
Me.Text = ofdThreadTest.SafeFileName & " Loading Now..." '...let the user know we're loading...
bwWorkerThread.RunWorkerAsync() '...then fire the bwWorkerThread DoWork event
End If
End Sub
'When you click "Stop"
Private Sub btnStop_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnStop.Click
btnStart.Enabled = True 'enable the start button, so the user can restart the process after it has been stopped
btnStop.Enabled = False 'disable the stop button, so that it can't be stopped when no longer in progress
If bwWorkerThread.IsBusy Then 'if the thread is active...
If bwWorkerThread.WorkerSupportsCancellation Then '...and it can be cancelled in-flight...
bwWorkerThread.CancelAsync() '...kill the thread
End If
End If
End Sub
'Background Thread Main Task
Private Sub bwWorkerThread_DoWork(ByVal sender As Object, ByVal e As DoWorkEventArgs) Handles bwWorkerThread.DoWork
Dim srFileTest As New IO.StreamReader(strFilePath)
Dim strDelimter As String = "|"
Dim intCounter As Integer = 0
Dim intFileLength As Integer = _
File.ReadAllLines(strFilePath).Length
Try
While srFileTest.Peek() >= 0
If bwWorkerThread.CancellationPending Then
e.Cancel = True
Exit While
Exit Try
End If
Dim strCurrentLine As String = srFileTest.ReadLine()
Dim strEntry As String() = strCurrentLine.Split(strDelimter.ToCharArray())
Dim objStore As New ExampleFile()
objStore.DataPoint = strEntry(0)
objStore.Process = strEntry(1)
SetListBox_ThreadSafe(Me.listOne, objStore.DataPoint)
SetListBox_ThreadSafe(Me.listTwo, objStore.Process)
intCounter = intCounter + 1
bwWorkerThread.ReportProgress(CInt((intCounter / intFileLength) * 100))
End While
Catch ex As Exception
MessageBox.Show("Something unexpected happened!", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
End Try
MessageBox.Show(intFileLength.ToString)
End Sub
'Background Thread Progress Updates
Private Sub bwWorkerThread_ProgressChanged(ByVal sender As Object, ByVal e As ProgressChangedEventArgs) Handles bwWorkerThread.ProgressChanged
Me.progMain.Value = e.ProgressPercentage
Me.Text = e.ProgressPercentage.ToString & "% Finished"
End Sub
'Background Thread Finished
Private Sub bwWorkerThread_RunWorkerCompleted(ByVal sender As Object, ByVal e As RunWorkerCompletedEventArgs) Handles bwWorkerThread.RunWorkerCompleted
If e.Cancelled Then
Me.Text = "File Test - Operation Cancelled!"
Else
Me.Text = "File Test - Finished!"
End If
End Sub
'Courier between bwWorkerThread and UI thread for list boxes
Delegate Sub SetListBox_Delegate(ByVal [ListBox] As ListBox, ByVal [value] As String)
Private Sub SetListBox_ThreadSafe(ByVal [ListBox] As ListBox, ByVal [value] As String)
If [ListBox].InvokeRequired Then
Dim MyListDelegate As New SetListBox_Delegate(AddressOf SetListBox_ThreadSafe)
Me.Invoke(MyListDelegate, New Object() {[ListBox], [value]})
Else
[ListBox].Items.Add([value])
End If
End Sub
End Class
'structure of example file in use
Public Class ExampleFile
Public Property DataPoint As String
Public Property Process As String
End Class