Ado*_*eVB 0 .net database vb.net loops
我的应用程序大约95%已完成,现在我正处于测试阶段..
我.exe在调试文件夹中使用该文件然后我使用该应用程序从gps模块的字符串突发中保存特定行以访问数据库..
这是流
样本数据

从gprmc到gpgsa = 1秒间隔.因此技术上模块每秒发送三行左右.
Try
Dim fruit As String = "$GPRMC"
For Each line As String In RichTextBox1.Lines
If line.Contains(fruit) Then
ProgressBar1.Value = 0
txt = line.Split(","c)
Insert()
End If
Next
Catch ex As Exception
sPort.Close()
MessageBox.Show("There had been no data received.", Me.Text, MessageBoxButtons.RetryCancel)
Call btnStartTimer_Click(sender, New EventArgs)
End Try
Run Code Online (Sandbox Code Playgroud)
下Minute_Tick,每60秒,Second.Start(它是上述代码).每一分钟,我RichTextBox在2秒后清除然后(再次填充rtb)我得到了$GPRMC它的线,.Split它到一个数组〜txt().从此以后,我将单词中的昏迷分隔开来.
现在我将它添加到数据库:
' Now inside a Using block
If txt(3) = String.Empty Then
.AddWithValue("@lat", 0)
Else
Dim la As Double = Double.Parse(txt(3).Substring(0, 2)) + Double.Parse(txt(3).Substring(2)) / 60.0
.AddWithValue("@lat", la)
End If
Run Code Online (Sandbox Code Playgroud)
txt(3)是Latitude DMS格式,所以我添加了一些转换片段.它工作正常,但我添加了一个条件,以确保它不会计算为null0或0值.
更新(我无法真正理解这段代码,因为我只是复制了它,但它与我创建的最后一个应用程序一起工作正常.)
Delegate Sub SetTextCallback(ByVal [text] As String)
Dim x As New SetTextCallback(AddressOf ReceivedText)
Private Sub SerialPort1_DataReceived(ByVal sender As Object, ByVal e As System.IO.Ports.SerialDataReceivedEventArgs) Handles sPort.DataReceived
ReceivedText(sPort.ReadExisting)
End Sub
Private Sub ReceivedText(ByVal [text] As String)
If Me.RichTextBox1.InvokeRequired Then
Me.Invoke(x, New Object() {(text)})
Else
Me.RichTextBox1.Text &= [text]
End If
End Sub
Run Code Online (Sandbox Code Playgroud)
麻烦我发现
我正在经历类似线程睡眠的事情.应用程序挂起,无法单击,无法关闭,但它在任务管理器上"运行",所以我认为它处于无限循环中,或者我错了?我结束了它在任务管理器上的关闭,并再次打开它.运行顺畅..然后,它会卡住.
我在思考,直到现在,是什么原因造成的?我认为它是因为模块不能总是得到一个信号,所以它什么都不返回..但如果模块没有给出坐标,它会在DB (上面的代码)中保存0 ,所以没有问题.
你们能帮帮我罪魁祸首吗?我在第三天,所以我决定需要一些帮助.谢谢.如果您需要任何或一些澄清,请告诉我.
If Me.RichTextBox1.InvokeRequired Then
Me.Invoke(x, New Object() {(text)})
Else
Me.RichTextBox1.Text &= [text]
End If
Run Code Online (Sandbox Code Playgroud)
你的代码是这样做的:

这是一个消防问题.问题始于SerialPort.ReadExisting()调用.通常返回一个或两个字符,串口很慢.在9600波特的常见波特率设置下,每秒可获得1000个字符,因此您可以有效地向RichTextBox添加新文本,每秒约500次,即可.
这会强制RichTextBox重新分配其内部缓冲区,该缓冲区存储文本并为额外添加的字符腾出空间,然后将旧缓冲区中的所有现有文本复制到新缓冲区并附加新文本.然后更新屏幕.
当您第一次启动程序时,这非常顺利,RichTextBox还没有包含太多文本.但是逐渐变得越来越贵,越来越多的角色必须被复制.
直到你达到一个临界点,复制开始花费太多时间,比你调用Me.Invoke()的速度更多的时间.UI线程现在开始落后,永远无法跟上.就像试图从消防水管中喝水一样.一旦完成复制内部缓冲区,就需要调度另一个调用请求,强制再次重新分配缓冲区.
UI线程现在停止处理其正常的低优先级职责.其中包括更新屏幕和处理输入事件.你注意到你的程序被冻结了,好像它已经陷入僵局.Windows将主窗口替换为"无响应"的重影窗口,并且敲击鼠标或键盘无效.您所能做的就是使用调试器或任务管理器终止程序并重新启动它.哪个工作正常,RichTextBox再次有一个空缓冲区,复制再次便宜.
请注意处理字符串时这是一般问题..NET Framework具有StringBuilder类来解决它.然而,这不适用于RichTextBox,您需要找到不同的解决方案.
所以你有效地向RichTextBox添加新文本大约每秒500次
你需要解决这个问题.以该速率向RTB添加文本毫无意义,没有人能够观察到如此高的速率.每秒添加20次文本已足够快,当你比这更快时,它开始看起来像模糊.或者换句话说,现在你做的比你需要快25倍.让RTB和UI线程都很难跟上这个速度.
另请注意,这可以解释您的解析问题.您正在解析不完整的文本行.因此,对此的一阶修复是仅在从串行端口获得完整的文本行时调用.这很容易来:
Private Sub SerialPort1_DataReceived(ByVal sender As Object, ByVal e As System.IO.Ports.SerialDataReceivedEventArgs) Handles sPort.DataReceived
ReceivedText(sPort.ReadLine)
End Sub
Run Code Online (Sandbox Code Playgroud)
换句话说,您要求串行端口返回整行文本而不是仅返回一个或两个字符.这会自动大大降低调用率并解决您的解析问题.
还有两件事你需要做.当程序运行足够长时,程序仍会挂起.您确实必须限制RTB中的文本量.当它存储超过65000个字符时,只丢掉一半.并且你必须删除对Close()方法的调用,这将导致真正的死锁,因为如果DataReceived调用仍然停留在ReadLine()调用中,则端口无法关闭.使用BeginInvoke()而不是Invoke(),减少死锁的危险.