4

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

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

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

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

4

5 回答 5

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
}
于 2013-07-25T05:56:24.737 回答
3

不幸的是,在 C# 中等待串行端口数据很棘手,没有什么像poll().

SerialPort.DataReceived需要对传入数据调用的函数。因此,您在那里分配了一个函数来触发任意事件。你的另一个函数——实际等待的函数——应该等待这个事件。

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

这只是一个示例,您可能希望重新制作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");
    }
}

}

更新:这个问题浪费了我一天的 1/2 时间,所以我希望我能节省一些人的时间:上面的代码在单声道 中不起作用(但在 MS 实现中起作用),因为在编写这些单词时不支持串行端口事件。

于 2014-10-17T10:10:59.103 回答
1

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

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

于 2013-07-25T05:54:17.450 回答
0

为什么不做一个全局标记(bool),如果你收到任何东西,做一个while(!marker){}循环,然后你在SerialPort_datareceived子程序中更改标记?

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

于 2013-07-25T05:56:02.813 回答
0

串行端口在单独的线程中工作。因此serialPort_DataReceived事件是从这个线程触发的。

因此,如果您的程序仅启动串行端口然后main退出,您将永远不会收到该事件。如果您有一个控制台应用程序,这是正确的。

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

于 2013-07-25T06:03:09.890 回答