【问题标题】:serial data only works with messagebox串行数据仅适用于消息框
【发布时间】:2012-08-31 01:58:45
【问题描述】:

在通过串行端口接收数据的处理程序中,当接收到数据时,我将其存储到字符串中并执行 .contains 搜索以确定是否需要对数据进行处理。当应用程序处于空闲状态并且(让我们称之为调制解调器)发送类似“已连接”的内容时,它可以正常工作。

问题是当我轮询机器时。当我启动一个期望返回结果的命令时它不起作用,我不知道为什么。现在,如果我使用消息框启动该功能,它将起作用。我宁愿没有不必要的消息框。

这是我的代码示例。

private void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e)
{
    if (this.InvokeRequired)
    {
        RefreshTextBox d = new RefreshTextBox(RefreshTextBoxResults);
        Invoke(d);
    }
    else
    {
        RefreshTextBoxResults();
    }
}

private void RefreshTextBoxResults()
{
    //MessageBox.Show("refresh text is occurring");
    indata1 = serialPort1.ReadExisting();
    rx.AppendText(indata1);

    string dataCheck = indata1.ToUpper();

    //MessageBox.Show(dataCheck);
    if (indata1.ToUpper().Contains("CONNECT"))//dataCheck.Contains("CONNECT"))
    {
        // MessageBox.Show("connect");
        cState.Text = "Connected";
        if(connected==false)
            connectLink();
    }
    if (dataCheck.Contains("CONNECTED"))
    {
        // MessageBox.Show("Active Call in Session");
        cState.Text = "Connected";
        if (connected==false)
            connectLink();
    }
    if (dataCheck.Contains("NO"))
    {
        cState.Text = "Disconnected";
        disconnect();
    }
    if (dataCheck.Contains("CAMPOS"))
    {
        campos = indata1;
        camDat = true;
    }
}

private void cState_Click(object sender, EventArgs e)
{
    writeDevice("callstatus");
}

public void writeDevice(string cmd)
{
    try
    {
        {
            serialPort1.Write(cmd + "\r\n");
        }
    }
    catch
    { noconnect(); }
}

当我执行 cstate() 时,它应该返回调用状态和类型(如果有)。正如我在提示框中看到的那样,调制解调器确实会响应。如果单词 connected 在那里的任何地方它应该将标签的文本更改为“Connected”。随着代码的放置,该标签没有任何反应。但是,如果我删除 RefreshTextBoxResults() 中第一行的注释,使 MessageBox 处于活动状态,它会检测调制解调器的状态。

我只是不明白发生了什么。有人可以向我解释为什么会这样吗?

【问题讨论】:

  • 您是否尝试将 indata1 放入消息框并查看它显示的内容?
  • 只是一个观察,前两个 if 语句: if (indata1.ToUpper().Contains("CONNECT")) 和 if (dataCheck.Contains("CONNECTED")) 做同样的事情.
  • 你为什么要使用很多如果你应该使用 if else 和 else ......
  • MessageBox 被阻塞,它在等待你点击“OK”时停止执行。如果你改为使用 Debug.WriteLine 会发生什么?
  • 绝对不要在DataReceived 事件处理程序中显示消息框或其他资源密集型任务。你只是自找麻烦。如果您只是进行故障排除或开发,最好记录信息或使用调试、跟踪或控制台。

标签: c# visual-studio-2010 serial-port


【解决方案1】:

但是,如果我删除 RefreshTextBoxResults() 中第一行的注释

这是关键短语。问题是您使用 ReadExisting()。串行端口非常慢,您的 DataReceived 事件处理程序通常只会得到一两个字符。通过显示消息框,您放慢了速度。这允许串行端口驱动程序读取 更多 个字符。足以让 ReadExisting 读取整个“Connected”字符串,而不仅仅是“C”或“Co”。

使用调试器时也很难诊断,单步执行代码也会减慢代码速度,以使端口能够获得足够的字符。

您需要做的是在获得整个响应字符串后处理响应。使用调制解调器总是很容易,只需使用 ReadLine() 而不是 ReadExisting()。您可能需要调整 NewLine 属性的值。

【讨论】:

  • 我将不得不尝试。我没有完全使用调制解调器,但它确实有很多相似的属性。
  • 这是金票。谢谢!
【解决方案2】:

MessageBox() 启动模式对话框消息循环,这将允许处理排队的窗口消息。可以想象,您在 RefreshTextboxResults() 函数中对文本框控件进行的某些操作会将消息发布到控件窗口句柄。如果是这种情况,窗口句柄将不会收到此类消息,直到执行流程进入或返回到消息循环。如果您打开一个模态对话框(如 MessageBox),这将在您的函数中发生。

并不是说这是一个解决方案,但它应该证实这个理论:尝试将MessageBox() 替换为对Application.DoEvents() 的调用。 (假设您的应用程序是 WinForms 应用程序)如果这清除阻塞的程度与调用 MessageBox() 相同,那么很明显您在消息队列中堆积了一些待处理的消息,需要处理。

【讨论】:

  • 我将 MessageBox() 替换为 Application.DoEvents(),但结果与 MessageBox 不同。
  • 好的,那么您的问题不在于排队的消息。
【解决方案3】:

我建议您在完全接收到数据之前阻止该应用程序,或者您可以使用后台踏板为您完成这项工作。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-12-09
    • 2017-03-18
    • 2021-08-21
    • 1970-01-01
    • 2016-01-27
    • 2020-04-12
    • 2013-06-23
    • 1970-01-01
    相关资源
    最近更新 更多