2014-01-11 39 views
0

我的應用程序是約95%完成了,現在我在測試階段..
我用.exe文件中debug文件夾中,然後我使用該應用從字符串一陣保存特定線從GPS模塊訪問數據庫..
這裏的流看不見的缺陷,應用stucks

示例數據
enter image description here
從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 

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 

txt(3)是緯度DMS格式,所以我加了一點轉換片段。它工作正常,但我添加了一個條件,以確保它不會計算null或0值。

UPDATE(我實在無法理解這個代碼,因爲我只是複製,但它正常工作與我創建的最後一個應用程序。)

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 

麻煩,我發現
我正在經歷類似於Threading Sleep的情況。應用程序掛起,無法點擊,無法關閉,但它在任務管理器上「運行」,所以我認爲它處於無限循環,或者我錯了?我結束了在任務管理器上的關閉,並再次打開它。運行順利..然後,它會卡住。
我在想,到現在爲止,是什麼原因造成的?我認爲它是因爲模塊不能總是得到一個信號,所以它什麼都沒有返回,但是如果模塊沒有給出座標,它在DB (代碼上面)中保存0,所以這沒有問題。

你們能幫我解決問題嗎?我在第三天,所以我決定我需要一些幫助。謝謝。讓我知道你是否需要任何說明或澄清。

+0

您是如何使用try..catch語句的,並且很難分析您提供的代碼片段。 – Jade

+0

檢查代碼更新。轉換代碼就是將我所調用的座標的DMS格式轉換爲由我使用的API讀取的十進制座標。 – AdorableVB

+0

txt(3)變量在解析時出錯。所以緯度值可能不是你所期望的。嘗試在某些文件上記下這些值,並檢查導致程序崩潰的值。順便說一下,接收到的確切錯誤信息是什麼? – Steve

回答

5
If Me.RichTextBox1.InvokeRequired Then 
    Me.Invoke(x, New Object() {(text)}) 
Else 
    Me.RichTextBox1.Text &= [text] 
End If 

你的代碼是這樣做的:

enter image description here

這是一個流水問題。該問題從SerialPort.ReadExisting()調用開始。通常返回一個或兩個字符,串行端口非常慢。在波特率爲9600波特的通用設置下,您每秒鐘可以獲得1000個字符,因此您可以有效地向RichTextBox添加約500次/秒的新文本。

這會強制RichTextBox重新分配存儲文本的內部緩衝區併爲額外添加的字符騰出空間,然後將舊緩衝區中的所有現有文本複製到新緩衝區中並追加新文本。然後更新屏幕。

當你第一次啓動你的程序時,這個過程非常順利,RichTextBox還沒有包含太多文本。但越來越昂貴,越來越多的角色必須被複制。

直到您到達複製開始花費太多時間的臨界點時,您調用Me.Invoke()的速度纔會更快。 UI線程現在開始落後,永遠無法跟上。就像試圖用消防水龍頭一樣喝水。一旦完成複製內部緩衝區,就需要調度另一個調用請求,迫使緩衝區重新分配。

UI線程現在停止處理其正常的低優先級職責。其中包括更新屏幕和處理輸入事件。你注意到你的程序被凍結,好像它已經僵持不下。 Windows用「沒有響應」的幻影窗口代替主窗口,並且敲擊鼠標或鍵盤沒有任何作用。你所能做的就是用調試器或任務管理器終止程序並重啓它。哪些工作正常,RichTextBox再次有一個空緩衝區和複製又便宜。

請注意這是處理字符串時的一般問題。 .NET框架有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 

換句話說,你要求串口返回一整行文本而不是一個或兩個字符。這會自動大大降低調用率並解決您的解析問題。

還有兩件事你必須做。運行時間足夠長時,程序仍然會掛起。您確實必須限制實時出價工具中的文字數量。當它存儲超過65000個字符時,只需將其中一半扔掉即可。您必須刪除對Close()方法的調用,這將導致真正的死鎖,因爲如果DataReceived調用仍然停留在ReadLine()調用中,則該端口無法關閉。使用BeginInvoke()而不是Invoke(),這樣可以減少死鎖的危險。

+0

驚人的解釋...... – Vikky

+0

我明白你的觀點,因此我並不真正理解RTB保存文本緩衝區的部分。每分鐘=清除RTB> ReadExisting>清除> ReadExisting ..我想到了這一點,因爲字符串的負載+定位我想要的行。不''rtb.clear()'刪除rtb的負載? – AdorableVB

+0

當然,它應該有所幫助。挑選60秒是一種猜測,顯然你需要的更少。如果文本滾動的速度太快以至於人們無法閱讀,那麼根本就沒有必要將它放入RTB中。 Anyhoo,而不是解決真正的問題。 –