【问题标题】:Is it not possible for two timer_tick events to work in parallel in reading the same data but performing different tasks?两个 timer_tick 事件是否不可能在读取相同数据但执行不同任务时并行工作?
【发布时间】:2012-07-30 11:36:19
【问题描述】:

我开发了一个 C# 应用程序来读取来自 GSM 调制解调器的呼叫。我使用 定时器 定期读取端口并在有来电时通知我。

现在我正在尝试使用另一个计时器,它将写入 AT+CSQ - 要了解端口上的信号质量,然后读取端口的质量值。在这两个计时器中,我都使用正则表达式来匹配和分离我需要的数据。现在的问题是,只有读取信号质量的我的 timer2 才有效,但不能读取来电的计时器。

定时器读取信号强度:

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;
                }
        }

为什么会发生这种情况以及解决方案?

【问题讨论】:

  • 你为什么不在一个定时器调用中同时拥有两者?
  • 我这里有一个典型的问题。我这样做了,但我的进度条没有显示任何东西。我使用断点来查看我的字符串已读取的内容,令我惊讶的是它读取正确,并且我的进度条显示了状态。但是当我直接运行我的应用程序时,进度条不显示任何内容。
  • 你会发现你无法通过线程来改变UI。如果我没记错的话,计时器使用线程,所以你需要使用 Invoke,即stackoverflow.com/questions/661561/…
  • 正确,常规 System.Timer 无法更新 UI DispachedTimer(如果使用 WPF)(msdn.microsoft.com/en-us/library/…)可以更新 UI,但如果运行时间长也会导致 UI 变得迟钝任务,例如轮询串行端口。

标签: c# regex timer progress-bar modem


【解决方案1】:

两个主要问题。首先是 ReadExisting(),它总是返回一个空字符串。除非您逐行调试和单步执行代码。这给了调制解调器足够的时间来发送响应。但这在您全速运行时不起作用,您需要进行阻塞调用,以确保您的程序等待足够长的时间以获取所有返回的字符。请改用 ReadLine()。

第二个杀手问题是您正在混合命令。您的 tmr_sig_quality_Tick() 方法可能会读取 timer1_Tick() 应该读取的任何内容。您需要重新考虑这种方法。类似于在收到对命令的响应之前不会前进的命令队列。

【讨论】:

  • 你说的第一个问题是ReadExisting(),可能第一次是空的,但至少在tick事件执行的2或3个间隔之后,读取会有一些响应吗?跨度>
  • 不,您在此之前使用 WriteLine() 并希望得到对该命令的响应。 ReadExisting() 不会给你那个响应,它返回一个空字符串。正如我所说,您需要重新考虑您的方法。
【解决方案2】:

不是您问题的实际答案,而是与 GSM 调制解调器通信的一般建议:

请记住,您只有一个串行端口,因此只有一个通信通道。 GSM 调制解调器可以发送自发事件,例如 RING、FAX、VOICE 事件,因此无法保证当您编写 AT+CSQ 时,第一个回复是您所期望的,即信号质量。

像您想要的那样拥有两个计时器并不是一个好主意,因为您最终会在计时器 A 中得到一个命令的响应,而在 B 中是预期的,因为 A 读取了其中一个自发事件...等等

一个更好和更健壮的方法是有一个工作线程来读取和解释传入的数据,然后根据需要将其分发到您的应用程序中。它还可以处理传出数据。使用并发队列和一些信号机制(即 AutoResetEvent)与该线程交换数据,这样您就可以获得更清晰的硬件设备接口,并且无需担心应用程序中的时间等问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-12-24
    • 2021-08-07
    • 2015-06-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多