C#等待串行端口上的数据
我试图通过c#应用程序从指纹扫描仪获取数据,但在指纹发送之前,我的整个代码都会执行 我尝试使用延迟函数和C#等待串行端口上的数据,c#,serial-port,delay,C#,Serial Port,Delay,我试图通过c#应用程序从指纹扫描仪获取数据,但在指纹发送之前,我的整个代码都会执行 我尝试使用延迟函数和System.Threading.Thread.Sleep(1000),这样它就可以在下一步执行之前获取数据,但这一切似乎都是徒劳的 有谁能提供其他选择吗 我正在使用“SerialPort\u DataReceived(object sender,SerialDataReceivedEventArgs e)”来获取数据。如果这是一个控制台应用程序,在调用COM端口组件的相应函数后,可以使用类似
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系统上唯一的实现)是否修复了串行端口事件。基本上,我根本没有办法帮你回答你的问题。好的,没问题!谢谢你的回复!