• <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

            思考、探索、實(shí)踐...... Rumination on C++
            posts - 2, comments - 22, trackbacks - 0, articles - 0
              C++博客 :: 首頁(yè) :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理

            C++ 事件機(jī)制實(shí)現(xiàn)

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

            一. 先看看事件接口定義和實(shí)現(xiàn)
            #ifndef IEVENT_H
            #define IEVENT_H


            /*
             以下各基礎(chǔ)設(shè)施是在C++中事件機(jī)制的完整實(shí)現(xiàn),事件是面向組件開(kāi)發(fā)的必要特性之一。
              
             創(chuàng) 作 者:sky
             時(shí)    間:2005.06.22 
             修訂時(shí)間:2005.06.22
            */

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

            class
             NullType
            {
            };

            // IEventHandler  是事件處理句柄,預(yù)定事件的類(lèi)從此接口繼承以實(shí)現(xiàn)事件處理函數(shù)

            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 事件預(yù)定方通過(guò)此接口預(yù)定事件

            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 事件發(fā)布方通過(guò)此接口觸發(fā)事件

            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 事件發(fā)布方發(fā)布事件相當(dāng)于就是發(fā)布一個(gè)IEventPublisher派生類(lèi)的對(duì)象
            // 不過(guò)僅僅將該對(duì)象的IEvent接口發(fā)布即可。

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

            // EventPublisher是IEventPublisher的默認(rèn)實(shí)現(xiàn)

            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
                上面的實(shí)現(xiàn)是淺顯易懂的,關(guān)鍵是要注意IEventPublisher的雙重身份-- 事件發(fā)布方最好發(fā)布IEvent指針給外部,而該指針實(shí)際指向的是一個(gè)EventPublisher對(duì)象,這是為了避免外部直接調(diào)用IEventActivator接口的方法。

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

            /*
             Timer 定時(shí)器,每經(jīng)過(guò)一段指定時(shí)間就觸發(fā)事件
             
             創(chuàng) 作 者:sky
             時(shí)    間:2005.06.22 
             修訂時(shí)間: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

                上面的示例清晰地說(shuō)明了如何發(fā)布一個(gè)事件,如何在適當(dāng)?shù)臅r(shí)候觸發(fā)事件,接下來(lái)看看如何預(yù)定事件。

            三. 預(yù)定事件例子

            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
            :
             
            //處理定時(shí)事件

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

                到這里,已經(jīng)將C++中的事件機(jī)制的實(shí)現(xiàn)及使用講清楚了。C#提供了很多便利的基礎(chǔ)設(shè)施來(lái)支持組件開(kāi)發(fā),而在C++中,這些基礎(chǔ)設(shè)施需要自己動(dòng)手來(lái)構(gòu)建,在擁有了這些設(shè)施之后,相信使用C++進(jìn)行組件開(kāi)發(fā)會(huì)輕松一點(diǎn)。

            Feedback

            # re: C++ 事件機(jī)制實(shí)現(xiàn)  回復(fù)  更多評(píng)論   

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

            # re: C++ 事件機(jī)制實(shí)現(xiàn)  回復(fù)  更多評(píng)論   

            2005-09-13 12:02 by atu

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

            # re: C++ 事件機(jī)制實(shí)現(xiàn)  回復(fù)  更多評(píng)論   

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

            # re: C++ 事件機(jī)制實(shí)現(xiàn)  回復(fù)  更多評(píng)論   

            2006-06-29 12:53 by dxf
            這個(gè)C++ 事件機(jī)制實(shí)現(xiàn),可不可放在GCC下編譯了..我試了,沒(méi)有成功....

            # re: C++ 事件機(jī)制實(shí)現(xiàn)  回復(fù)  更多評(píng)論   

            2007-01-24 16:31 by csdn.wuyazhe(我的寶貝叫阿刺)
            請(qǐng)問(wèn)你的stl是什么地方下載的,我找不到SafeArrayList.h文件。能否發(fā)給我一份。謝謝:)
            simtel_006@126.com
            91精品国产9l久久久久| 性高湖久久久久久久久AAAAA| 九九久久99综合一区二区| 国产精品狼人久久久久影院| 人妻无码久久精品| 久久er国产精品免费观看2| 日韩欧美亚洲综合久久影院Ds | 久久精品国产99国产精偷| 久久男人中文字幕资源站| 久久综合给合久久狠狠狠97色 | 国产精品美女久久久免费| 久久综合五月丁香久久激情| 香蕉久久夜色精品升级完成| 亚洲国产二区三区久久| 欧美噜噜久久久XXX| 天天影视色香欲综合久久| 久久国产精品一区二区| 亚洲精品蜜桃久久久久久| 久久久久久无码国产精品中文字幕 | 精品久久久无码中文字幕| 久久久噜噜噜www成人网| 久久综合久久综合亚洲| 久久久久久免费一区二区三区| 国产成人久久精品一区二区三区| 99久久精品国产一区二区| 久久久久无码精品国产不卡| 伊人久久一区二区三区无码| 中文精品久久久久国产网址 | 久久青青草原精品国产| 亚洲人成无码www久久久| 国产日韩久久免费影院| 久久99国产精品99久久| 久久天堂AV综合合色蜜桃网| 亚洲人成电影网站久久| 久久综合久久性久99毛片| 国产一区二区精品久久凹凸 | 亚洲国产成人久久综合碰| 久久久久亚洲爆乳少妇无| 国产高清国内精品福利99久久| 久久香蕉国产线看观看99| 久久99国产乱子伦精品免费|