2012-07-30 27 views
2

我開發了一個C#應用程序來讀取來自GSM調制解調器的呼叫。我使用定時器定期讀取端口,並在有來電時通知我。兩個timer_tick事件不可能在讀取相同數據但並行執行不同任務時並行工作?

現在我正在嘗試使用另一個定時器,它會寫入AT + CSQ - 要知道信號質量,請在端口上讀取端口的質量值。在兩個定時器中,我使用正則表達式來匹配和分離我需要的數據。現在的問題是,只有我的定時器2這是讀取信號質量只是工作,但不是計時器讀取來電。

定時器讀信號強度:

private void tmr_sig_quality_Tick(object sender, EventArgs e) 
    { 
     if (port.IsOpen) 
     { 
      port.WriteLine("AT+CSQ"); 
      string s= port.ReadExisting(); 
      var match= Regex.Match(s,@"\+CSQ: (\d+),(\d+)"); 
      if (match.Success) 
      { 
       progressBar1.Value = int.Parse(match.Groups[1].Value); 
      } 

     } 
    } 

定時讀取來電:

 private void timer1_Tick(object sender, EventArgs e) 
     { 
       s = port.ReadExisting(); 

       var match = Regex.Match(s, "RING[^\\+]*\\+CLIP:\\s*\"(?<phone>[^\"]*)\",(\\d+),\"([^\"]*)\",(\\w*),\"(\\w*)\",(\\w*)"); 

       if (match.Success && s.Contains("RING")) 
       { 
        incall_status.Text = "Incoming Call...." + match.Groups["phone"].Value; 
        incall_status.Visible = true; 
       } 
     } 

爲什麼發生這種情況和解決方案嗎?

+1

爲什麼你沒有在一個單一的計時器呼叫? – Gavin 2012-07-30 12:27:07

+0

我在這裏有一個典型的問題。我這樣做,但我的進度條沒有顯示任何東西。我使用斷點來查看我的字符串已經閱讀了什麼,並且我驚訝地發現它正確地閱讀,並且我的進度條顯示了狀態。但是當我直接運行我的應用程序時,進度條不顯示任何內容。 – Cdeez 2012-07-30 12:43:50

+0

你會發現你不能通過線程來改變UI。如果我沒有記錯,定時器使用線程,所以你需要使用Invoke,即http:// stackoverflow。COM /問題/ 661561 /如何對更新 - 桂 - 從-另一個線程在-C – Gavin 2012-07-30 12:52:30

回答

2

兩個主要問題。首先是ReadExisting(),它將始終返回一個空字符串。除非您正在逐行調試和逐行執行代碼。這給調制解調器足夠的時間來發送響應。但是當你全速運行時,這是行不通的,你需要進行阻塞調用,以確保程序等待足夠長的時間以獲取所有返回的字符。使用ReadLine()代替。

第二個殺手問題是你在混合命令。您的tmr_sig_quality_Tick()方法可能讀取任何timer1_Tick()應該讀取的內容。你需要重新考慮這種方法。類似於接收到對命令的響應之前不會前進的命令隊列。

+0

第一個問題,因爲你有ReadExisting()說,可能是第一次這將是空的,但蜱事件執行的ATLEAST後2周或3的間隔會有一些反應看對不對? – Cdeez 2012-07-31 08:46:29

+0

不,您在此之前使用WriteLine(),並希望獲得對該命令的響應。 ReadExisting()不會給你那個響應,它會返回一個空字符串。正如我所說,你需要重新思考你的方法。 – 2012-07-31 08:51:37

1

不是一個實際的回答你的問題,但對於一個GSM調制解調器通信的一般建議:

請記住,你只有一個串行端口,因此只有一個通信通道。 GSM調制解調器可以發送自發事件,例如RING,FAX,VOICE事件,所以不能保證當你寫AT + CSQ時,第一個答覆就是你所期望的,即信號質量。

有兩個像你打算的定時器是不是一個好主意,因爲你最終會結束在定時器A中的一個命令的響應,因爲它預計在B中,因爲A讀取了一個自發事件。 。等等。

一個更好更健壯的方法是擁有一個工作線程來讀取和解釋傳入數據,然後根據需要將其分發到您的應用程序中。它也可以處理傳出的數據。使用併發隊列和一些信號機制(例如AutoResetEvent)與該線程交換數據,這樣您就可以獲得更清晰的硬件設備接口,無需擔心應用程序中的時序等問題。

相關問題