更多开源请访问:51CTO开源基础软件社区https://ost.51cto.comEventHandler是用于处理线程间的一种机制-通信,可以通过EventRunner创建一个新线程,在新线程上执行耗时操作。这样就不会阻塞原来的线程,可以合理的处理任务。例如:主线程使用EventHandler创建子线程,子线程做耗时的图片下载操作。下载完成后,子线程通过EventHandler通知主线程,主线程更新UI。基本概念EventRunner是一个事件循环器,循环从EventRunner创建的新线程的事件队列中获取InnerEvent事件。InnerEvent是EventHandler传递的事件。EventHandler是用户将当前线程上的InnerEvent事件发布到异步线程进行处理的一种机制。每个EventHandler都绑定了一个由指定的EventRunner创建的新线程,新线程内部有一个事件队列。EventHandler可以将指定的InnerEvent事件传递给这个事件队列。EventRunner循环从事件队列中取事件,在EventRunner所在线程执行processEvent回调。一般来说,Eve??ntHandler有两个主要功能:在不同线程之间分发和处理InnerEvent事件。延迟处理InnerEvent事件。运行机制使用EventHandler实现线程间通信的主要过程:EventHandler将具体的InnerEvent事件传递到EventRunner创建的线程的事件队列中。EventRunner循环从事件队列中获取InnerEvent事件。在新的线程上处理事件:触发InnerEvent的回调方法,触发EventHandler的处理方法。接口说明:ohos.events.emitter(Emitter)进程中的InnerEvent事件。EventData发送事件时传递的数据。EventPriority用于指示正??在传递的事件的优先级。代码目录:foundation/└──foundation/appexecfwk/standard├──interfaces│├──innerkits│|└──libeventhandler#内部接口│└──napi│└──eventhandler#NAPI接口└──libs/libeventhandler#机制实现代码类图:EventRunner:EventRunner的create方法会在创建Runner线程的同时实例化一个EventQueue,赋值给类内部的成员变量queue_。EventRunner的Runner线程轮询queue_,取出队列中的InnerEvent事件,处理事件。EventHandler:EventHandler的每个Send方法通过调用EventQueue的Insert方法将InnerEvent插入到EventQueue的subEventQueues_或idleEvents__中。当调用Post方法传递回调函数时,会将回调函数赋值给InnerEvent的taskCallback_,通过Send方法将带有回调函数的InnerEvent插入到队列中。其中,subEventQueues_是一个大小为3的SubEventQueue列表,3个SubEventQueue分别用来存放三个不同优先级(IMMEDIATE/HIGH/LOW)的InnerEvents。idleEvents_用于存放优先级为IDLE的InnerEvents。同样,Remove方法是从上面的subEventQueue_或idleEvent_中删除一个事件。EventQueue通过成员变量ioWaiter_获取定时或延迟的InnerEvent事件。同时实现文件描述符监听事件的回调。ioWaiter_成员的类型默认为NoneIoWaiter,此时不支持文件描述符监听。通过NoneIoWaiter调用std::condition_variable机制实现队列中延迟或定时事件的获取。当调用EventHandler中的AddFileDescriptorListener时,ioWaiter_成员的类型自动转换为EpollIoWaiter类型。EpollIoWaiter支持监听文件描述符的事件。此时通过系统的epoll机制取出队列中的延迟或定时事件。关键字代码摘录:EventRunner//启动事件循环器。for(autoevent=queue_->GetEvent();event;event=queue_->GetEvent()){//监听轮询queue_std::shared_ptrhandler=event->GetOwner();//确保事件的所有者存在。如果(处理程序){std::shared_ptrlogging=logger_;std::stringstream地址;地址<HasTask()){logging->Log("Dispatchingtohandlereventid="+std::to_string(event->GetInnerEventId()));}else{logging->Log("Dispatchingtohandlereventtaskname="+event->GetTaskName());}}处理程序->DistributeEvent(事件);//执行aInnerEvent事件if(logging!=nullptr){logging->Log("Finishedtohandler(0x"+address.str()+")");}}//手动释放事件,否则事件将被释放直到下一个事件到来。事件.重置();}EventQueuevoidEventQueue::Insert(InnerEvent::Pointer&event,Prioritypriority)//事件或任务的插入{if(!event){HILOGE("Insert:Couldnotinsertaninvalidevent");返回;}std::lock_guard锁(queueLock_);boolneedNotify=false;switch(priority){//根据Event的优先级将应该Event插入不同的事件列表casePriority::IMMEDIATE:casePriority::HIGH:casePriority::LOW:{needNotify=(event->GetHandleTime()(priority)].queue,event);休息;}casePriority::IDLE:{//如果插入空闲事件,则永远不会唤醒线程。插入rtEventsLocked(idleEvents_,事件);休息;默认值:中断;}if(needNotify){ioWaiter_->NotifyOne();}}InnerEvent::PointerEventQueue::GetEvent()//事件或任务的取出{std::unique_locklock(queueLock_);while(!finished_){InnerEvent::TimePointnextWakeUpTime=InnerEvent::TimePoint::max();InnerEvent::指针事件=GetExpiredEventLocked(nextWakeUpTime);如果(事件){返回事件;}WaitUntilLocked(nextWakeUpTime,锁);}HILOGD("GetEvent:爆发");returnInnerEvent::Pointer(nullptr,nullptr);}EventHandlervoidEventHandler::DistributeEvent(constInnerEvent::Pointer&event)//执行InnerEvent事件{if(!event){HILOGE("DistributeEvent:Couldnotdistributeaninvalidevent");返回;}//保存旧的事件处理程序。std::weak_ptroldHandler=currentEventHandler;//节省当前事件处理程序到线程本地数据。currentEventHandler=shared_from_this();autospanId=event->GetTraceId();autotraceId=HiTrace::GetId();boolallowTraceOutPut=AllowHiTraceOutPut(spanId,event->HasWaiter());如果(allowTraceOutPut){HiTrace::SetId(*spanId);HiTracePointerOutPut(spanId,事件,"接收",HiTraceTracepointType::HITRACE_TP_SR);InnerEvent::TimePointnowStart=InnerEvent::Clock::now();DeliveryTimeAction(事件,现在开始);if(event->HasTask()){//如果有回调函数//如果包含任务,直接调用任务回调。(事件->GetTaskCallback())();//执行回调函数}else{//否则让开发者处理。ProcessEvent(事件);//执行ProcessEvent}DistributeTimeAction(event,nowStart);if(allowTraceOutPut){HiTrace::Tracepoint(HiTraceTracepointType::HITRACE_TP_SS,*spanId,"事件分发结束");HiTrace::ClearId();如果(traceId.IsValid()){HiTrace::SetId(traceId);}}//恢复当前事件处理程序。if(oldHandler.expired()){currentEventHandler=nullptr;}else{currentEventHandler=oldHandler;}}了解更多开源请访问:51CTO开源基础软件社区https://ost.51cto.com