我试图通过c#应用程序从指纹扫描程序获取数据,但在指纹发送之前,我的整个代码都会执行。
我尝试使用延迟函数和System.Threading.Thread.Sleep(1000)
,因此它可以在下一步执行之前获取数据,但这一切似乎都是徒劳的。
任何人都可以提供其他选择吗?
我正在使用“SerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
”来获取数据。
答案 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
初始化并打开一个串口(特别是指定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实现中工作)因为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。
使用表单应用程序时,它会使表单和主线程保持活动状态,直到用户关闭它。