• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            zhuweisky

            思考、探索、實踐...... Rumination on C++
            posts - 2, comments - 22, trackbacks - 0, articles - 0
              C++博客 :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理

            C++ 事件機制實現

            Posted on 2005-09-11 20:15 zhuweisky 閱讀(5713) 評論(5)  編輯 收藏 引用 所屬分類: C++組件技術
               事件是面向組件開發的必要特性之一,但C++不直接支持事件,沒關系,我自己實現了一個,感覺很好用,分享給大家!
               最開始打算用函數指針模擬事件,但由于C++中成員函數指針不能和void*相互強轉,而且 typedef中不能含有模板,所以才不得已以接口繼承實現。這樣效果也不錯 :)

            一. 先看看事件接口定義和實現
            #ifndef IEVENT_H
            #define IEVENT_H


            /*
             以下各基礎設施是在C++中事件機制的完整實現,事件是面向組件開發的必要特性之一。
              
             創 作 者:sky
             時    間:2005.06.22 
             修訂時間:2005.06.22
            */

            #include 
            "../Collection/SafeArrayList.h"
            template
            <class SenderType ,class ParaType> class EventPublisher ;

            class
             NullType
            {
            };

            // IEventHandler  是事件處理句柄,預定事件的類從此接口繼承以實現事件處理函數

            template<class SenderType ,class ParaType>
            interface IEventHandler
            {

            public
            :
             
            virtual ~
            IEventHandler(){}
            private
            :
             
            virtual void HandleEvent(SenderType sender ,ParaType para)  = 0
             ;
             friend 
            class EventPublisher<SenderType ,ParaType>
             ;
            };

            // IEvent 事件預定方通過此接口預定事件

            template<class SenderType ,class ParaType>
            interface IEvent
            {
            public
            :

             
            virtual ~
            IEvent(){}
             
            virtual void Register  (IEventHandler<SenderType ,ParaType>* handler) = 0
             ;  
             
            virtual void UnRegister(IEventHandler<SenderType ,ParaType>* handler) = 0
             ;
            };

            // IEventActivator 事件發布方通過此接口觸發事件

            template<class SenderType ,class ParaType>
            interface IEventActivator
            {
            public
            :

             
            virtual ~
            IEventActivator(){}
             
            virtual void Invoke(SenderType sender ,ParaType para) = 0
            ;
             
            virtual int  HandlerCount() = 0
            ;
             
            virtual IEventHandler<SenderType ,ParaType>* GetHandler(int index) = 0
            ;
            };

            //
             IEventPublisher 事件發布方發布事件相當于就是發布一個IEventPublisher派生類的對象
            // 不過僅僅將該對象的IEvent接口發布即可。

            template<class SenderType ,class ParaType>
            interface IEventPublisher : public IEvent<SenderType ,ParaType> ,public IEventActivator<SenderType ,ParaType> 
            {
            };

            // EventPublisher是IEventPublisher的默認實現

            template<class SenderType ,class ParaType>
            class EventPublisher :public IEventPublisher<SenderType ,ParaType>
            {
            private:
             SafeArrayList
            < IEventHandler<SenderType ,ParaType> >
             handerList ;
             IEventHandler
            <SenderType ,ParaType>*
             innerHandler ;

            public
            :
             
            void Register(IEventHandler<SenderType ,ParaType>*
             handler) 
             {
              
            this->
            handerList.Add(handler) ;
             }

             
            void UnRegister(IEventHandler<SenderType ,ParaType>*
             handler)
             {
              
            this->
            handerList.Remove(handler) ;
             }

             
            void
             Invoke(SenderType sender ,ParaType para)
             {
              
            int count = this->
            handerList.Count() ;
              
            for(int i=0 ;i<count ;i++
            )
              {
               IEventHandler
            <SenderType ,ParaType>* handler = this->
            handerList.GetElement(i) ;
               handler
            ->
            HandleEvent(sender ,para) ;
              }
             } 

             
            int
              HandlerCount()
             {
              
            return this->
            handerList.Count() ;
             }

             IEventHandler
            <SenderType ,ParaType>* GetHandler(int
             index)
             {
              
            return this->
            handerList.GetElement(index) ;
             }
            };

            #endif
                上面的實現是淺顯易懂的,關鍵是要注意IEventPublisher的雙重身份-- 事件發布方最好發布IEvent指針給外部,而該指針實際指向的是一個EventPublisher對象,這是為了避免外部直接調用IEventActivator接口的方法。

            二. 一個定時器類Timer,演示如何發布事件。想必大家都知道定時器的用途了哦,這個Timer就像C#中的Timer類一樣。
            #ifndef TIMER_H
            #define TIMER_H

            /*
             Timer 定時器,每經過一段指定時間就觸發事件
             
             創 作 者:sky
             時    間:2005.06.22 
             修訂時間:2005.06.22
            */
            #include 
            "IEvent.h"
            #include 
            "Thread.h"

            void TimerThreadStart(void* para) ;

            class
             Timer
            {
            private
            :
             
            int
             spanInMillSecs ;
             
            volatile bool
             isStop ;
             
            volatile bool
             timerThreadDone ;
             
            public
            :
             friend 
            void TimerThreadStart(void*
             para) ;
             IEvent
            <Timer* ,NullType>*
             TimerTicked ;

             Timer(
            int
             span_InMillSecs) 
             {
              
            this->isStop = true
             ;
              
            this->timerThreadDone = true
             ;
              
            this->spanInMillSecs =
             span_InMillSecs ;
              
            this->TimerTicked = new EventPublisher<Timer* ,NullType>
             ;
             }
             
             
            ~
            Timer()
             {
              
            this->
            Stop() ;
              delete 
            this->
            TimerTicked ;
             } 

             
            void
             Start()
             {
              
            if(! this->
            isStop)
              {
               
            return
             ;
              }

              
            this->isStop = false
             ;
              Thread thread ;
              thread.Start(TimerThreadStart ,
            this
            ) ;
              
            //
            unsigned int  dwThreadId ;
              
            //HANDLE hThread = (HANDLE)_beginthreadex(NULL, 0 , (unsigned int (_stdcall*)(void*))&TimerThreadStart , this, 0, &dwThreadId);   

              
             }

             
            void
             Stop()
             {
              
            ifthis->
            isStop)
              {
               
            return
             ;
              }
              
              
            this->isStop = true
             ;

              
            //等待工作線程退出

              while(! this->timerThreadDone)
              {
               Sleep(
            200
            ) ;
              }
             }

            private

             
            void
             WorkerThread()
             {
              
            this->timerThreadDone = false
             ;

              
            while(! this->
            isStop)
              {  
               Sleep(
            this->
            spanInMillSecs) ;

               
            if(this->
            isStop)
               {
                
            break
             ;
               }
               
               NullType nullObj ;
               ((EventPublisher
            <Timer* ,NullType>*)this->TimerTicked)->Invoke(this
             ,nullObj) ;
              }

              
            this->timerThreadDone = true
             ;
             }
            };

            void TimerThreadStart(void*
             para)
            {
                Timer
            * timer = (Timer*
            )para ;
                timer
            ->
            WorkerThread() ;
            }
            #endif

                上面的示例清晰地說明了如何發布一個事件,如何在適當的時候觸發事件,接下來看看如何預定事件。

            三. 預定事件例子

            class TimerEventExample  :public IEventHandler<Timer* ,NullType> ,CriticalSection
            {
            private
            :
             Timer
            *
             timer ;
             
            public
            :
             TimerEventExample(
            int
             checkSpan) 
             {  
              
            this->timer = new
             Timer(checkSpan) ;
              
            this->timer->TimerTicked->Register(this
            ) ;
             }

             
            ~
            TimerEventExample()
             {
              delete 
            this->
            timer ;
             } 

            private
            :
             
            //處理定時事件

             void HandleEvent(Timer* sender ,NullType para)
             {
              cout
            <<"Time ticked !"<<
            endl ;
             }
            };

                到這里,已經將C++中的事件機制的實現及使用講清楚了。C#提供了很多便利的基礎設施來支持組件開發,而在C++中,這些基礎設施需要自己動手來構建,在擁有了這些設施之后,相信使用C++進行組件開發會輕松一點。

            Feedback

            # re: C++ 事件機制實現  回復  更多評論   

            2005-09-12 08:49 by moonriver
            寫的很清楚, 謝謝!

            # re: C++ 事件機制實現  回復  更多評論   

            2005-09-13 12:02 by atu

            沒看到 template<class SenderType ,class ParaType>
            interface IEventHandler 的實現,這樣你的示例中((EventPublisher<Timer* ,NullType>*)this->TimerTicked)->Invoke(this ,nullObj) ;如何工作?

            # re: C++ 事件機制實現  回復  更多評論   

            2005-09-14 21:15 by zhuweisky
            to atu :
            請注意這句
            class TimerEventExample :public IEventHandler<Timer* ,NullType> ,CriticalSection

            # re: C++ 事件機制實現  回復  更多評論   

            2006-06-29 12:53 by dxf
            這個C++ 事件機制實現,可不可放在GCC下編譯了..我試了,沒有成功....

            # re: C++ 事件機制實現  回復  更多評論   

            2007-01-24 16:31 by csdn.wuyazhe(我的寶貝叫阿刺)
            請問你的stl是什么地方下載的,我找不到SafeArrayList.h文件。能否發給我一份。謝謝:)
            simtel_006@126.com
            亚洲国产高清精品线久久| 狠狠色丁香久久婷婷综合五月| 狠狠色综合网站久久久久久久| 国产精品免费久久久久电影网| 久久这里只有精品视频99| 日韩美女18网站久久精品| 色综合久久综合中文综合网| 久久九九青青国产精品| 亚洲综合久久久| 久久精品无码一区二区app| 久久久精品国产| 国产精品免费久久久久电影网| 国产精品99久久久精品无码| 国产免费福利体检区久久| 久久亚洲春色中文字幕久久久| 久久无码一区二区三区少妇| 久久99精品久久久久久久不卡 | 久久综合一区二区无码| 久久久精品国产sm调教网站| 亚洲а∨天堂久久精品9966| 办公室久久精品| 国产精品久久久久久福利69堂| 久久久噜噜噜久久中文字幕色伊伊| 嫩草影院久久国产精品| 精品免费久久久久久久| 久久国语露脸国产精品电影| 亚洲中文字幕伊人久久无码| 欧美精品福利视频一区二区三区久久久精品 | 新狼窝色AV性久久久久久| 人妻中文久久久久| 91精品免费久久久久久久久| 26uuu久久五月天| 久久青青草原综合伊人| 久久久久久久99精品免费观看| 97久久综合精品久久久综合| 999久久久无码国产精品| 99久久人妻无码精品系列蜜桃 | 精品国产VA久久久久久久冰| 9久久9久久精品| 国产成人无码精品久久久免费| 精品国产91久久久久久久a |