单线程事件驱动模型
由于只有一个线程,监听到事件后必须马上处理。这样在处理过程中,会忽略掉期间到来的事件。如果处理时间不长,并且事件到来不是特别频繁,可以使用单线程。
有些事件在监听前,必须申请一些资源,如打开文件,打开设备等。因此处理时间前必须释放响应的资源,这为编程增加了一些复杂性。
要注意事件之间的优先级,如果两个事件同时到来,只有先被尝试检测的事件有效,另一个事件会被丢弃。
大致流程如下:
打开串口设备;
打开非接读卡器;//串口和非接读卡器需要动态打开关闭
生成资源释放事件并入队;//关闭串口,关闭非接设备
while(没超时)
{
尝试读按键;//非阻塞
if(读到数据)
{
继续读,直到读完为止;
生成按键事件并入队;
break;
}
尝试读磁条读卡器;//刷卡器和IC读卡器始终是打开状态,和键盘一样
if(读到数据)
{
继续读,直到读完为止;
生成磁条读卡事件并入队;
break;
}
尝试读IC读卡器;
if(读到数据)
{
继续读,直到读完为止;
生成IC读卡事件并入队;
break;
}
尝试读非接读卡器;
if(读到数据)
{
继续读,直到读完为止;
生成非接读卡事件并入队;
break;
}
尝试读串口;
if(读到数据)
{
继续读,直到读完为止;
生成串口事件并入队;
break;
}
msleep(10);//避免轮询过快}
if(超时了)生成超时事件并入队;
while(事件队列不空)取出一个事件并处理;
单线程的优点是逻辑简单,不需要处理线程之间的关系与通信。缺点是如果事件到来得很频繁,有些事件可能会被丢弃。
多线程事件驱动模型
每个线程监听一种事件,可以保证事件被及时地检测到,而且不会丢失事件。资源管理由每个独立的线程执行,可以在线程启动时申请资源,结束时释放资源。
举例如下:
thread 1:
while(1)
{
尝试读按键;//可以阻塞在此
if(读到数据)
{
继续读,直到读完为止;
获得事件队列的锁;
生成按键事件并入队;
释放事件队列的锁;
}
}
thread 2:
while(1)
{
if(队列为空)
{
msleep(10);//避免轮询过快
continue;
}
获得事件队列的锁;
取出事件并处理;
释放事件队列的锁;
}
多线程的优点是事件不会丢失,事件在任何时间点到来都能被捕获。缺点是要处理好线程之间的关系,不要死锁。有时处理完一个事件后需要通知其他线程,还要实现进程间通讯。
嵌入式设备大都配置不高,在我的项目中始终使用的是单线程模型。处理的事件具有较好的互斥性,即不会有两个事件同时到达,因此单线程可以满足需求。