为什么我的 Sub 一次只打印 1 行而不是 30 行?
Why is my Sub printing only 1 line at a time instead of 30?
我目前正在为 xmr-stak 编写 GUI (www.xmrgui.com)
从程序中获取输出时遇到一些问题,基本上想从输出文本文件中获取最后 30 行,如果它们不存在,则将它们附加到 RichTextBox 中。将文本文件存储在内存中不是一个大问题,因为它每 20 分钟左右就会被删除一次……至少我认为是这样。也许我的功能占用了太多内存或时间。
我唯一的要求是 Sub TimerOutput_tick 可以处理文件中最后 30 行文本中的每一行,并在每行上 运行 一个正则表达式,并且 RichTextBox 不会重复旧信息.
这是我的代码:
Private Function getlastlines(filename As String, numberOfLines As Integer) As Dictionary(Of Integer, String)
Try
Dim fs = File.Open(filename, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)
Dim reader As StreamReader = New StreamReader(fs)
Dim everything As New Dictionary(Of Integer, String)
Dim n As Integer = 1
While reader.Peek > -1
Dim line = reader.ReadLine()
If everything.ContainsKey(n) Then
everything(n) = line
n += 1
Else
everything.Add(n, line)
n += 1
End If
End While
Dim results As New Dictionary(Of Integer, String)
Dim z As Integer = 1
If n - numberOfLines > 0 Then
For x As Integer = n - numberOfLines To n - 1
'MsgBox(everything.Count - numberOfLines)
If results.ContainsKey(z) Then
results(z) = everything(x)
z += 1
Else
results.Add(z, everything(x))
z += 1
End If
Next
End If
Return results
Catch ex As Exception
MsgBox(ex.ToString)
End Try
End Function
' GRABS XMR-STAK OUTPUT FROM ReadLastLinesFromFile AND RUNS A REGEX ON THE HASHRATE TO PROVIDE VALUES TO THE CHART
这里是调用前一个函数的 Sub:
Private Sub timeroutput_Tick(sender As Object, e As EventArgs) Handles timeroutput.Tick
'Try
Dim lateststring = getlastlines(xmroutput, 30)
Try
If lateststring IsNot rtlateststring Then
Dim kvp As KeyValuePair(Of Integer, String)
For Each kvp In lateststring
If lateststring.ContainsKey(kvp.Key) Then
Dim line = kvp.Value
RichTextBox1.AppendText(line & vbCrLf)
If line.Contains("Totals") Then ' Should be "Totals"
'Dim regex As Regex = New Regex("\d+?.\d+")
Dim regex As Regex = New Regex("\d{1,5}\.\d{1,1}") ' match a double
Dim ret = regex.Match(line).Value
If ret <> "" Then
Dim iSpan As TimeSpan = TimeSpan.FromSeconds(upseconds)
Label8.Text = "Uptime - Hours: " & iSpan.Hours & " Minutes: " & iSpan.Minutes & " Seconds: " & iSpan.Seconds & " " & ret & " H/s"
NotifyIcon1.Text = "Uptime - Hours: " & iSpan.Hours & vbCrLf & " Minutes: " & iSpan.Minutes & vbCrLf & " Seconds: " & iSpan.Seconds & vbCrLf & ret & " H/s"
Else
Dim iSpan As TimeSpan = TimeSpan.FromSeconds(upseconds)
NotifyIcon1.Text = "Uptime - Hours: " & iSpan.Hours & vbCrLf & " Minutes: " & iSpan.Minutes & vbCrLf & " Seconds: " & iSpan.Seconds & vbCrLf & "Initializing..."
Label8.Text = "Uptime - Hours: " & iSpan.Hours & " Minutes: " & iSpan.Minutes & " Seconds: " & iSpan.Seconds & " Initializing..."
ret = "0.0"
End If
'Dim match As Match = regex.Match(lastline)
newhashrate = Convert.ToDouble(ret)
ElseIf line.Contains("NVIDIA") Then
Dim regexnv As Regex = New Regex("\d{1,5}\.\d{1,1}") ' match a double
Dim retnv = regexnv.Match(line).Value
newNVhashRate = Convert.ToDouble(retnv)
If firstNV = False Then
newser.Add(nvidiacard1)
nvidiacard1.Title = "NIVIDIA Hashrate(H/s)"
nvidiacard1.Values = nvidiavalues
nvidiavalues.add(0)
nvidiavalues.add(4)
nvidiavalues.add(2)
nvidiavalues.add(5)
firstNV = True
End If
ElseIf line.Contains("AMD") Then
Dim regexAMD As Regex = New Regex("\d{1,5}\.\d{1,1}") ' match a double
Dim retAMD = regexAMD.Match(line).Value
newAMDhashrate = Convert.ToDouble(retAMD)
If firstAMD = False Then
newser.Add(AMDCard1)
AMDCard1.Title = "AMD Hashrate(H/s)"
AMDCard1.Values = AMDValues
AMDValues.add(0)
AMDValues.add(4)
AMDValues.add(2)
AMDValues.add(5)
firstAMD = True
End If
End If
' Now if a GPU exists, add a new lineseries for CPU
If firstAMD = True Or firstNV = True Then
If firstCPU = False Then
newser.Add(CPU1)
CPU1.Title = "CPU Hashrate(H/s)"
CPU1.Values = CPUValues
CPUValues.add(0)
CPUValues.add(4)
CPUValues.add(2)
CPUValues.add(5)
firstCPU = True
End If
newCPUhashrate = newhashrate - newNVhashRate - newAMDhashrate
End If
rtlateststring = lateststring
End If
Next
RichTextBox1.SelectionStart = RichTextBox1.Text.Length
End If
Catch
End Try
End Sub
我找到了一个更简单的解决方案,运行 一个函数中的代码,然后将整个文本文件加载到 richtextbox 中。从那里单独阅读最后十行要容易得多:
Private Sub timeroutput_Tick(sender As Object, e As EventArgs) Handles timeroutput.Tick
Try
'Dim lateststring = getlastlines(xmroutput, 30)
' START NEW TEST
Dim fs = File.Open(xmroutput, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)
Dim reader As StreamReader = New StreamReader(fs)
Dim wholefile = reader.ReadToEnd
RichTextBox1.Text = wholefile
RichTextBox1.SelectionStart = RichTextBox1.Text.Length
For x As Integer = 1 To 10
Dim line As String = RichTextBox1.Lines(RichTextBox1.Lines.Length - x)
If line.Contains("Totals") Then ' Should be "Totals"
'Dim regex As Regex = New Regex("\d+?.\d+")
Dim regex As Regex = New Regex("\d{1,5}\.\d{1,1}") ' match a double
Dim ret = regex.Match(line).Value
If ret <> "" Then
Dim iSpan As TimeSpan = TimeSpan.FromSeconds(upseconds)
Label8.Text = "Uptime - Hours: " & iSpan.Hours & " Minutes: " & iSpan.Minutes & " Seconds: " & iSpan.Seconds & " " & ret & " H/s"
NotifyIcon1.Text = "Uptime - Hours: " & iSpan.Hours & vbCrLf & " Minutes: " & iSpan.Minutes & vbCrLf & " Seconds: " & iSpan.Seconds & vbCrLf & ret & " H/s"
Else
Dim iSpan As TimeSpan = TimeSpan.FromSeconds(upseconds)
NotifyIcon1.Text = "Uptime - Hours: " & iSpan.Hours & vbCrLf & " Minutes: " & iSpan.Minutes & vbCrLf & " Seconds: " & iSpan.Seconds & vbCrLf & "Initializing..."
Label8.Text = "Uptime - Hours: " & iSpan.Hours & " Minutes: " & iSpan.Minutes & " Seconds: " & iSpan.Seconds & " Initializing..."
ret = "0.0"
End If
'Dim match As Match = regex.Match(lastline)
newhashrate = Convert.ToDouble(ret)
ElseIf line.Contains("NVIDIA") Then
Dim regexnv As Regex = New Regex("\d{1,5}\.\d{1,1}") ' match a double
Dim retnv = regexnv.Match(line).Value
newNVhashRate = Convert.ToDouble(retnv)
If firstNV = False Then
newser.Add(nvidiacard1)
nvidiacard1.Title = "NIVIDIA Hashrate(H/s)"
nvidiacard1.Values = nvidiavalues
For Each z In Chartvalues
Chartvalues.remove(z)
Next
nvidiavalues.add(0)
firstNV = True
End If
ElseIf line.Contains("AMD") Then
Dim regexAMD As Regex = New Regex("\d{1,5}\.\d{1,1}") ' match a double
Dim retAMD = regexAMD.Match(line).Value
newAMDhashrate = Convert.ToDouble(retAMD)
If firstAMD = False Then
newser.Add(AMDCard1)
AMDCard1.Title = "AMD Hashrate(H/s)"
AMDCard1.Values = AMDValues
For Each z In Chartvalues
Chartvalues.remove(z)
Next
AMDValues.add(0)
firstAMD = True
End If
End If
' Now if a GPU exists, add a new lineseries for CPU
If firstAMD = True Or firstNV = True Then
If firstCPU = False Then
newser.Add(CPU1)
CPU1.Title = "CPU Hashrate(H/s)"
CPU1.Values = CPUValues
For Each z In Chartvalues
Chartvalues.remove(z)
Next
CPUValues.add(0)
Chartvalues.add(0)
firstCPU = True
End If
newCPUhashrate = newhashrate - newNVhashRate - newAMDhashrate
End If
Next
Catch
End Try
' END NEW TEST
End Sub
我目前正在为 xmr-stak 编写 GUI (www.xmrgui.com) 从程序中获取输出时遇到一些问题,基本上想从输出文本文件中获取最后 30 行,如果它们不存在,则将它们附加到 RichTextBox 中。将文本文件存储在内存中不是一个大问题,因为它每 20 分钟左右就会被删除一次……至少我认为是这样。也许我的功能占用了太多内存或时间。
我唯一的要求是 Sub TimerOutput_tick 可以处理文件中最后 30 行文本中的每一行,并在每行上 运行 一个正则表达式,并且 RichTextBox 不会重复旧信息.
这是我的代码:
Private Function getlastlines(filename As String, numberOfLines As Integer) As Dictionary(Of Integer, String)
Try
Dim fs = File.Open(filename, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)
Dim reader As StreamReader = New StreamReader(fs)
Dim everything As New Dictionary(Of Integer, String)
Dim n As Integer = 1
While reader.Peek > -1
Dim line = reader.ReadLine()
If everything.ContainsKey(n) Then
everything(n) = line
n += 1
Else
everything.Add(n, line)
n += 1
End If
End While
Dim results As New Dictionary(Of Integer, String)
Dim z As Integer = 1
If n - numberOfLines > 0 Then
For x As Integer = n - numberOfLines To n - 1
'MsgBox(everything.Count - numberOfLines)
If results.ContainsKey(z) Then
results(z) = everything(x)
z += 1
Else
results.Add(z, everything(x))
z += 1
End If
Next
End If
Return results
Catch ex As Exception
MsgBox(ex.ToString)
End Try
End Function
' GRABS XMR-STAK OUTPUT FROM ReadLastLinesFromFile AND RUNS A REGEX ON THE HASHRATE TO PROVIDE VALUES TO THE CHART
这里是调用前一个函数的 Sub:
Private Sub timeroutput_Tick(sender As Object, e As EventArgs) Handles timeroutput.Tick
'Try
Dim lateststring = getlastlines(xmroutput, 30)
Try
If lateststring IsNot rtlateststring Then
Dim kvp As KeyValuePair(Of Integer, String)
For Each kvp In lateststring
If lateststring.ContainsKey(kvp.Key) Then
Dim line = kvp.Value
RichTextBox1.AppendText(line & vbCrLf)
If line.Contains("Totals") Then ' Should be "Totals"
'Dim regex As Regex = New Regex("\d+?.\d+")
Dim regex As Regex = New Regex("\d{1,5}\.\d{1,1}") ' match a double
Dim ret = regex.Match(line).Value
If ret <> "" Then
Dim iSpan As TimeSpan = TimeSpan.FromSeconds(upseconds)
Label8.Text = "Uptime - Hours: " & iSpan.Hours & " Minutes: " & iSpan.Minutes & " Seconds: " & iSpan.Seconds & " " & ret & " H/s"
NotifyIcon1.Text = "Uptime - Hours: " & iSpan.Hours & vbCrLf & " Minutes: " & iSpan.Minutes & vbCrLf & " Seconds: " & iSpan.Seconds & vbCrLf & ret & " H/s"
Else
Dim iSpan As TimeSpan = TimeSpan.FromSeconds(upseconds)
NotifyIcon1.Text = "Uptime - Hours: " & iSpan.Hours & vbCrLf & " Minutes: " & iSpan.Minutes & vbCrLf & " Seconds: " & iSpan.Seconds & vbCrLf & "Initializing..."
Label8.Text = "Uptime - Hours: " & iSpan.Hours & " Minutes: " & iSpan.Minutes & " Seconds: " & iSpan.Seconds & " Initializing..."
ret = "0.0"
End If
'Dim match As Match = regex.Match(lastline)
newhashrate = Convert.ToDouble(ret)
ElseIf line.Contains("NVIDIA") Then
Dim regexnv As Regex = New Regex("\d{1,5}\.\d{1,1}") ' match a double
Dim retnv = regexnv.Match(line).Value
newNVhashRate = Convert.ToDouble(retnv)
If firstNV = False Then
newser.Add(nvidiacard1)
nvidiacard1.Title = "NIVIDIA Hashrate(H/s)"
nvidiacard1.Values = nvidiavalues
nvidiavalues.add(0)
nvidiavalues.add(4)
nvidiavalues.add(2)
nvidiavalues.add(5)
firstNV = True
End If
ElseIf line.Contains("AMD") Then
Dim regexAMD As Regex = New Regex("\d{1,5}\.\d{1,1}") ' match a double
Dim retAMD = regexAMD.Match(line).Value
newAMDhashrate = Convert.ToDouble(retAMD)
If firstAMD = False Then
newser.Add(AMDCard1)
AMDCard1.Title = "AMD Hashrate(H/s)"
AMDCard1.Values = AMDValues
AMDValues.add(0)
AMDValues.add(4)
AMDValues.add(2)
AMDValues.add(5)
firstAMD = True
End If
End If
' Now if a GPU exists, add a new lineseries for CPU
If firstAMD = True Or firstNV = True Then
If firstCPU = False Then
newser.Add(CPU1)
CPU1.Title = "CPU Hashrate(H/s)"
CPU1.Values = CPUValues
CPUValues.add(0)
CPUValues.add(4)
CPUValues.add(2)
CPUValues.add(5)
firstCPU = True
End If
newCPUhashrate = newhashrate - newNVhashRate - newAMDhashrate
End If
rtlateststring = lateststring
End If
Next
RichTextBox1.SelectionStart = RichTextBox1.Text.Length
End If
Catch
End Try
End Sub
我找到了一个更简单的解决方案,运行 一个函数中的代码,然后将整个文本文件加载到 richtextbox 中。从那里单独阅读最后十行要容易得多:
Private Sub timeroutput_Tick(sender As Object, e As EventArgs) Handles timeroutput.Tick
Try
'Dim lateststring = getlastlines(xmroutput, 30)
' START NEW TEST
Dim fs = File.Open(xmroutput, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)
Dim reader As StreamReader = New StreamReader(fs)
Dim wholefile = reader.ReadToEnd
RichTextBox1.Text = wholefile
RichTextBox1.SelectionStart = RichTextBox1.Text.Length
For x As Integer = 1 To 10
Dim line As String = RichTextBox1.Lines(RichTextBox1.Lines.Length - x)
If line.Contains("Totals") Then ' Should be "Totals"
'Dim regex As Regex = New Regex("\d+?.\d+")
Dim regex As Regex = New Regex("\d{1,5}\.\d{1,1}") ' match a double
Dim ret = regex.Match(line).Value
If ret <> "" Then
Dim iSpan As TimeSpan = TimeSpan.FromSeconds(upseconds)
Label8.Text = "Uptime - Hours: " & iSpan.Hours & " Minutes: " & iSpan.Minutes & " Seconds: " & iSpan.Seconds & " " & ret & " H/s"
NotifyIcon1.Text = "Uptime - Hours: " & iSpan.Hours & vbCrLf & " Minutes: " & iSpan.Minutes & vbCrLf & " Seconds: " & iSpan.Seconds & vbCrLf & ret & " H/s"
Else
Dim iSpan As TimeSpan = TimeSpan.FromSeconds(upseconds)
NotifyIcon1.Text = "Uptime - Hours: " & iSpan.Hours & vbCrLf & " Minutes: " & iSpan.Minutes & vbCrLf & " Seconds: " & iSpan.Seconds & vbCrLf & "Initializing..."
Label8.Text = "Uptime - Hours: " & iSpan.Hours & " Minutes: " & iSpan.Minutes & " Seconds: " & iSpan.Seconds & " Initializing..."
ret = "0.0"
End If
'Dim match As Match = regex.Match(lastline)
newhashrate = Convert.ToDouble(ret)
ElseIf line.Contains("NVIDIA") Then
Dim regexnv As Regex = New Regex("\d{1,5}\.\d{1,1}") ' match a double
Dim retnv = regexnv.Match(line).Value
newNVhashRate = Convert.ToDouble(retnv)
If firstNV = False Then
newser.Add(nvidiacard1)
nvidiacard1.Title = "NIVIDIA Hashrate(H/s)"
nvidiacard1.Values = nvidiavalues
For Each z In Chartvalues
Chartvalues.remove(z)
Next
nvidiavalues.add(0)
firstNV = True
End If
ElseIf line.Contains("AMD") Then
Dim regexAMD As Regex = New Regex("\d{1,5}\.\d{1,1}") ' match a double
Dim retAMD = regexAMD.Match(line).Value
newAMDhashrate = Convert.ToDouble(retAMD)
If firstAMD = False Then
newser.Add(AMDCard1)
AMDCard1.Title = "AMD Hashrate(H/s)"
AMDCard1.Values = AMDValues
For Each z In Chartvalues
Chartvalues.remove(z)
Next
AMDValues.add(0)
firstAMD = True
End If
End If
' Now if a GPU exists, add a new lineseries for CPU
If firstAMD = True Or firstNV = True Then
If firstCPU = False Then
newser.Add(CPU1)
CPU1.Title = "CPU Hashrate(H/s)"
CPU1.Values = CPUValues
For Each z In Chartvalues
Chartvalues.remove(z)
Next
CPUValues.add(0)
Chartvalues.add(0)
firstCPU = True
End If
newCPUhashrate = newhashrate - newNVhashRate - newAMDhashrate
End If
Next
Catch
End Try
' END NEW TEST
End Sub