条形码扫描仪以异步方式运行,因此必须在数据可用或设备状态发生更改时通知应用程序。 需要使用 .NET 委托执行此任务,向应用程序引发事件。
如设备输入和事件主题中所述,事件在传送到应用程序之前,会排入队列。 Microsoft Point of Service for .NET (POS for .NET) Base 类为服务对象代码提供了一种将事件排入队列的方法,这样可以延迟将事件传递到应用程序,直到应用程序可以处理这些事件。 同时,服务对象可以继续等待其他传入硬件事件。
扫描仪设备可以向应用程序发送四个事件。 对于其中两个事件(DataEvent 和 ErrorEvent),POS for .NET ScannerBase 类提供了一种受保护的帮助程序方法,用于简化引发这些事件所需的代码:
事件 | 将事件排入队列的方法 |
---|---|
DataEvent | 受保护的方法 ScannerBase.GoodRead |
ErrorEvent | 受保护的方法 ScannerBase.FailedRead |
其他两个事件(DirectIOEvent 和 StatusUpdateEvent)必须通过较低级别的 ScannerBasic 类的成员引发。 有关详细信息,请参阅设备输入和事件。
由于扫描仪设备可以随时将数据传递到系统,因此扫描仪服务对象必须通过启动一个单独的阅读器线程来异步等待数据。 当来自设备的数据到达时,事件应从此线程排入队列。
基于设备输入引发事件
启动阅读器线程,等待来自设备的输入。
在阅读器线程上等待输入,最常见的方法是使用 Win32 直接函数从 USB 总线读取数据。
收到数据后,验证数据是否有效,例如,数据包中是否有足够的字节用于标头和数据类型。
如果数据无效,请调用 ScannerBase.FailedScan 方法,将应用程序中引发的 ErrorEvent 事件排入队列。
如果数据有效,请调用 ScannerBase.GoodScan 方法,将应用程序中最终引发的 DataEvent 事件排入队列。
示例
一旦接收到来自设备的输入,服务对象就会将相应的事件排入队列。 为此,可以编写一种方法,例如本主题示例中将从服务对象的阅读器线程调用的方法。
// A Service Object may implement a method such as this one to
// be called from the reader thread of the Service Object.
void OnDataScanned(byte[] data)
{
// Ignore input if process in the Error state. There is no
// need to send an ErrorEvent to the application, because it has
// already been notified by this point.
if (State == ControlState.Error)
{
return;
}
// Make sure that the incoming buffer is large enough to contain
// at least the header and type data.
if ((int)data[1] < 5)
{
// By calling FailedRead, you are queueing an
// ErrorEvent for eventual delivery to the application.
FailedScan();
}
else
{
// The buffer received from the device will be longer
// than we need. Therefore, trim it down. Allocate space for
// the number of bytes contained in data[1], plus one
// more for the first byte in the buffer.
byte[] b = new byte[(int)data[1] + 1];
// Copy the data into a new buffer.
for (int i = 0; i <= (int)data[1]; i++)
{
b[i] = data[i];
}
// By calling GoodScan, you are queueing a DataEvent
// which will delivered to the application when it is suitable.
GoodScan(b);
}
}
此示例无法自行编译,但可以将它插入到完整的扫描仪服务对象实现中。