C#等待串口数据

时间:2013-07-25 05:49:28

标签: c# serial-port delay

我试图通过c#应用程序从指纹扫描程序获取数据,但在指纹发送之前,我的整个代码都会执行。

我尝试使用延迟函数和System.Threading.Thread.Sleep(1000),因此它可以在下一步执行之前获取数据,但这一切似乎都是徒劳的。

任何人都可以提供其他选择吗?

我正在使用“SerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)”来获取数据。

5 个答案:

答案 0 :(得分:3)

这段代码非常适合我:

port = new SerialPort(port, 9600, Parity.None, 8, StopBits.One);
port.Open();
port.DiscardOutBuffer();
port.DiscardInBuffer();
port.DataReceived += OnScan;

void OnScan(object sender, SerialDataReceivedEventArgs args)
{
    SerialPort port = sender as SerialPort;

    string line = port.ReadExisting();
// etc
}

答案 1 :(得分:2)

不幸的是,在C#中等待串口数据很棘手,没有类似poll()的内容。

SerialPort.DataReceived可以在传入数据上调用函数。因此,您可以为其分配一个触发任意事件的函数。你的另一个功能 - 实际等待的功能 - 应该等待这个事件。

下面是一个简单的示例,它被注释,但简而言之:TestFunc初始化并打开一个串口(特别是指定DataReceivedProxy()是一个函数,每次数据到达时都会调用它,它会触发一个事件。并且WaitForAData()确实等待数据出现时由Proxy()触发的事件。请注意lock(){} s,如果没有它们围绕Monitor的功能,它将无法正常工作。

这只是一个例子,您可能希望重新发送WaitForAData()函数以在超时的情况下触发异常。如果在开始等待之前触发了Proxy(),则添加一个布尔变量,然后串口已经有数据。但我测试了它(因为我现在需要这样的功能☺),它可以工作。

namespace MyNamespace
{

class MySerial
{
    ///A condition variable that signals when serial has a data
    private System.Object SerialIncoming;

    public MySerial()
    {
        SerialIncoming = new Object();
    }

    /**
     * A proxy function that will be called every time a data arrived
     */
    private void Proxy(Object unused1, SerialDataReceivedEventArgs unused2)
    {
        Console.WriteLine("Data arrived!");
        lock (SerialIncoming)
        {
            Monitor.Pulse(SerialIncoming);
        }
    }

    /**
     * Waits for a data for the time interval Timeout
     * \param Timeout a timeout in milliseconds to wait for a data
     * \returns true in if a data did arrived, and false else
     */
    public bool WaitForAData(int Timeout)
    {
        lock (SerialIncoming)//waits N seconds for a condition variable
        {
            if (!Monitor.Wait(SerialIncoming, Timeout))
                {//if timeout
                    Console.WriteLine("Time out");
                    return false;
                }
            return true;
        }
    }

    /* Just a test function: opens a serial with speed, and waits
     * for a data for the «Timeout» milliseconds.
     */
    public void TestFunc(string serial, int speed, int Timeout)
    {
        SerialPort ser = new SerialPort(serial);
        ser.BaudRate = speed;
        ser.DataReceived += Proxy;
        ser.Open();
        if (WaitForAData(Timeout))
            Console.WriteLine("Okay in TestFunc");
        else
            Console.WriteLine("Time out in TestFunc");
    }
}

}

更新:这个问题浪费了我一天的时间,所以我希望我能节省一些时间:上面的代码无法在 mono 中使用(但是在MS实现中工作)因为serial port events are not supported写这些单词。

答案 2 :(得分:1)

如果这是一个控制台应用程序,在调用COM端口组件的相应功能后,可以使用Console.ReadLine()等内容来开始异步监听。如果这是一个WinForms应用程序。消息循环当然会继续显示您当前的表单。在这种情况下,您可以在Form_Load事件或按钮单击后调用异步侦听功能。

这里的关键点是你应该调用监听器函数的异步版本。在这种情况下,无需使用延迟或计时器。

答案 3 :(得分:0)

为什么不制作一个全局标记(bool),标记您是否收到了任何内容并进行了一段时间(!标记){}循环并更改了SerialPort_datareceived子变换中的标记?

thread.sleep可能会让你错过SerialPort数据发送?

答案 4 :(得分:0)

串口工作在一个单独的线程中。因此,serialPort_DataReceived事件从此线程触发。

因此,如果您的程序仅启动串行端口,然后main退出,则您永远不会收到该事件。如果您有控制台应用程序,则为true。

使用表单应用程序时,它会使表单和主线程保持活动状态,直到用户关闭它。