C#等待串行端口上的数据

C#等待串行端口上的数据,c#,serial-port,delay,C#,Serial Port,Delay,我试图通过c#应用程序从指纹扫描仪获取数据,但在指纹发送之前,我的整个代码都会执行 我尝试使用延迟函数和System.Threading.Thread.Sleep(1000),这样它就可以在下一步执行之前获取数据,但这一切似乎都是徒劳的 有谁能提供其他选择吗 我正在使用“SerialPort\u DataReceived(object sender,SerialDataReceivedEventArgs e)”来获取数据。如果这是一个控制台应用程序,在调用COM端口组件的相应函数后,可以使用类似

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

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

有谁能提供其他选择吗


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

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


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

为什么不制作一个全局标记(bool),它可以标记您是否接收到任何内容,并进行while(!marker){}循环,然后更改SerialPort_datareceived子例程中的标记


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

此代码非常适合我:

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
}

串行端口在单独的线程中工作。因此,
serialPort\u DataReceived
事件从此线程触发

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


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

不幸的是,在C#中等待串行端口数据非常棘手,没有什么比
poll()
更好的了

SerialPort.DataReceived
,它接受对传入数据调用的函数。因此,在这里指定一个函数来触发任意事件。您的另一个函数(实际等待的函数)应该等待此事件

下面是一个简单的示例,有注释,但简而言之:
TestFunc
初始化并打开一个串行端口(特别是分配
DataReceived
)。
Proxy()
是一个函数,每次数据到达时都会调用它,它会触发一个事件。而
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实现中起作用)因为在写这些词的时候。

发布代码,所以有人可以帮助你。谢谢你的输入。我是C#的新手。请你解释一下如何定义异步侦听函数。它是一个Windows窗体应用程序。我相信你使用的是
SerialPort
类。这个类默认情况下只在同步模式下工作,所以你需要将它与
BackgroundWorker
组件一起使用(或使用您自己的后台线程机制)。检查
BackgroundWorker
组件的使用情况。它非常简单且易于使用。您花在学习此组件上的时间将在未来几天给您带来大量回报。如果收到一些数据并执行线程。sleep()正在运行时,它将丢弃该数据???
线程。Sleep
用于当前线程。从其他线程调用
DataReceived
事件,因此您将接收数据。这将是因为您必须更改线程间的值,以便找到如何将一个线程中的值更改为另一个线程中的值。它不等待数据,它只是读取了一个现有的数据。@Hi Angel我认为代码应该按预期工作。DataReceived将仅在收到数据时(而不是立即)调用委托OnScan@Offler是的。但是询问者期望的是一个在SerialPort上等待的代码。我的情况也是这样:假设我有某种串行连接,我想在几秒钟内等待一个数据,如果数据没有到达,那么返回到假设连接断开。这不是Servè编写的代码。顺便说一句,在problem@Hi-天使但是如果你如果你真的只想这样做,那么忘记所有事件可能会更容易。为了访问arduino“serial=new SerialPort(port,baudRate){ReadTimeout=2000}”;然后“try{int returnValue=serial.ReadByte();returnValue;}catch(TimeoutException),我做了以下操作//将在2秒后发生->中断”。之后,您不需要一堆监视器等。(好的,与arduino的通信是一个业余项目中自己的线程-此线程中的所有内容都按顺序运行…)@Offler不,这是一种悲哀。我是认真的。你能帮我一下吗:@PrashantPimpale抱歉,我已经有几年没有使用C#了,希望我将来不会:)此外,我手边也没有串行端口,我也不知道Mono(自从我手边没有Windows以来,在非Windows系统上唯一的实现)是否修复了串行端口事件。基本上,我根本没有办法帮你回答你的问题。好的,没问题!谢谢你的回复!