我正在尝试通过 c# 应用程序从指纹扫描仪获取数据,但在指纹可以发送之前,我的整个代码都会执行。
我尝试使用延迟函数 and System.Threading.Thread.Sleep(1000)
,所以它可以在下一步执行之前获取数据,但这一切似乎都是徒劳的。
任何人都可以提供任何其他选择吗?
我正在使用“ SerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
”来获取数据。
我正在尝试通过 c# 应用程序从指纹扫描仪获取数据,但在指纹可以发送之前,我的整个代码都会执行。
我尝试使用延迟函数 and System.Threading.Thread.Sleep(1000)
,所以它可以在下一步执行之前获取数据,但这一切似乎都是徒劳的。
任何人都可以提供任何其他选择吗?
我正在使用“ SerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
”来获取数据。
这段代码非常适合我:
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
}
不幸的是,在 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 实现中起作用),因为在编写这些单词时不支持串行端口事件。
Console.ReadLine()
如果这是一个控制台应用程序,您可以在调用 COM 端口组件的相应函数后使用诸如此类的东西来开始异步侦听。如果这是一个 WinForms 应用程序。消息循环当然会继续显示您当前的表单。Form_Load
在这种情况下,您可以在事件中或单击按钮后调用异步侦听函数。
这里的关键是你应该调用监听函数的异步版本。在这种情况下,无需使用延迟或计时器。
为什么不做一个全局标记(bool),如果你收到任何东西,做一个while(!marker){}循环,然后你在SerialPort_datareceived子程序中更改标记?
thread.sleep 可能会让您错过 SerialPort 数据发送?
串行端口在单独的线程中工作。因此serialPort_DataReceived
事件是从这个线程触发的。
因此,如果您的程序仅启动串行端口然后main
退出,您将永远不会收到该事件。如果您有一个控制台应用程序,这是正确的。
使用表单应用程序时,它会保持表单和主线程处于活动状态,直到用户关闭它。