是使用后台工作者的正确方法

时间:2012-07-20 11:04:13

标签: c# serial-port modem at-command

我想在c#应用程序中阅读来自GSM调制解调器的消息。我编写了以下代码并使用后台工作程序在单独的线程上实现Thread.sleep()。但是我使用port.ReadExisting()的时候,没有从端口读取任何东西。我使用错误的处理后台工作者的方式吗?

    private void btn_Read_Click(object sender, EventArgs e)
    {
        lvwMessages.Items.Clear();
        status_other.Visible = true;
        status_other.Text = "Loading messages...";
        if (read_all.Checked)
        {
            port.WriteLine("AT+CMGL=\"ALL\"");

        }
        else if (read_unread.Checked)
        {
            port.WriteLine("AT+CMGL=\"REC UNREAD\"");
        }
        port.DiscardOutBuffer();
        port.DiscardInBuffer();

        backgroundWorker1.RunWorkerAsync();
    }
    private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
    {
        Thread.Sleep(5000);
    }

    private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
     string res = port.ReadExisting();// here no data is fetched into res
        //rest of the code

2 个答案:

答案 0 :(得分:2)

实际上,如果portSerialPort,那么你做错了。 SerialPort有一个DataReceived事件是异步的,在数据​​进入时会自动调用。这样您就可以逐步构建答案,并在收到完整邮件时检测代码答复。

你可以依靠等待5秒来获得完整回复。

示例:

private String m_receivedData = String.Empty;

private void port_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
    m_receivedData += (sender as SerialPort).ReadExisting();

    if (<check whether m_receivedData contains everything I need> == true)
    {
        ProcessData(m_receivedData);
        m_receivedData = String.Empty;
    }
}

请注意port_DataReceived在单独的线程中调用,因此如果要更新GUI,则需要使用Invoke

修改
只是为了说清楚:应该使用BackgroundWorker在后​​台执行操作,报告状态和/或报告完成时间。仅使用它来暂停并不是一件有用的事情,特别是当实际过程确实包括一些&#34;等到数据出现时#34;机制,这是我上面描述的事件。

答案 1 :(得分:1)

是的,你以错误的方式使用后台工作人员 更好的是使用SerialPort的直接数据接收事件,或者如果你想使用基于时间的解决方案,一次性计时器会更好。