将此置于后台工作人员是否会停止此问题



我已经尝试解决这个问题好几天了,但没有成功。我知道我已经创建了另一个与这个问题相关的帖子,但不确定我是否应该继续使用另一个帖子,而不是创建一个新的帖子,因为我对SO的工作方式还很陌生,所以如果我做错了,我很抱歉。

目标
从磁盘读取文本文件,将内容输出到文本框中,这样我就可以从中提取最后3行。这是我能想到的唯一方法。

另一个正在运行的程序不断更新文本文件,但即使它在使用中,我仍然可以读取它,但无法写入。

我正在通过计时器探测这个文件,计时器每1秒一次,以获取最新信息。

现在是问题
我注意到,一段时间后,我的应用程序变得迟钝,当我试图在屏幕上移动它或调整它的大小时,这一点很明显,CPU使用率开始攀升至超过33%的

我的思考过程
由于读取文件是一个连续的过程,我想我可以将它移到BackgroundWorker上,根据我的理解,它会将它放在另一个线程上,并减轻主GUI的一些负载。

我是不是找错树了?

在我开始学习如何使用BackgroundWorker之前,我正在接触更高级的用户。

这是我用来读取txt文件并将其输出到文本框的代码。我没有包含提取最后3行的代码,因为我不认为这部分会导致问题。

我认为这个问题是因为我每秒都在用计时器不断地探查源文件,但老实说,我不能100%确定。

Dim strLogFilePath As String
strLogFilePath = "C:DSDdata.txt"
Dim LogFileStream As FileStream
Dim LogFileReader As StreamReader
'Open file for reading
LogFileStream = New FileStream(strLogFilePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)
LogFileReader = New StreamReader(LogFileStream)
'populate text box with the contents of the txt file
Dim strRowText As String
strRowText = LogFileReader.ReadToEnd()
TextBox1.text = strRowText
'Clean Up
LogFileReader.Close()
LogFileStream.Close()
LogFileReader.Dispose()
LogFileStream.Dispose()

首先,您应该使用Using关键字,而不是手动处理对象,因为这样可以保证即使发生意外异常,对象也会被处理,例如:

' You can initialize variables in one line
Dim strLogFilePath As String = "C:DSDdata.txt"
Using LogFileStream As New FileStream(strLogFilePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)
' Everything goes in here
End Using

我的解决方案不需要读者。读数将手动完成。

接下来,您需要读取流的最后n行(在本例中为3行(。当你只对最后的几行感兴趣时,阅读整个文件是低效的。相反,你可以从最后开始阅读,直到达到三个(或任意数量(行分隔符(基于这个答案(:

Function ReadLastLines(
NumberOfLines As Integer, Encoding As System.Text.Encoding, FS As FileStream,
Optional LineSeparator As String = vbCrLf
) As String
Dim NewLineSize As Integer = Encoding.GetByteCount(LineSeparator)
Dim NewLineCount As Integer = 0
Dim EndPosition As Long = Convert.ToInt64(FS.Length / NewLineSize)
Dim NewLineBytes As Byte() = Encoding.GetBytes(LineSeparator)
Dim Buffer As Byte() = Encoding.GetBytes(LineSeparator)
For Position As Long = NewLineSize To EndPosition Step NewLineSize
FS.Seek(-Position, SeekOrigin.End)
FS.Read(Buffer, 0, Buffer.Length)
If Encoding.GetString(Buffer) = LineSeparator Then
NewLineCount += 1
If NewLineCount = NumberOfLines Then
Dim ReturnBuffer(CInt(FS.Length - FS.Position)) As Byte
FS.Read(ReturnBuffer, 0, ReturnBuffer.Length)
Return Encoding.GetString(ReturnBuffer)
End If
End If
Next
' Handle case where number of lines in file is less than NumberOfLines
FS.Seek(0, SeekOrigin.Begin)
Buffer = New Byte(CInt(FS.Length)) {}
FS.Read(Buffer, 0, Buffer.Length)
Return Encoding.GetString(Buffer)
End Function

用法:

Using LogFileStream As New FileStream(strLogFilePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)
' Depending on system, you may need to supply an argument for the LineSeparator param
Dim LastThreeLines As String = ReadLastLines(3, System.Text.Encoding.UTF8, LogFileStream)
' Do something with the last three lines
MsgBox(LastThreeLines)
End Using

请注意,我还没有测试过这个代码,我相信它可以改进。它可能也不适用于所有编码,但听起来它应该比您当前的解决方案更好,而且它将适用于您的情况。

编辑:此外,为了回答您的问题,IO操作通常应该异步执行,以避免阻塞UI。您可以使用任务或BackgroundWorker来完成此操作。它可能不会让它更快,但会让你的应用程序反应更灵敏。最好在任务开始前表明有东西正在加载。

如果您知道文件的写入时间,可以设置一个开始读取的标志,然后在读取最后一行时取消设置。如果它没有改变,就没有理由反复阅读。

相关内容

最新更新