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

            牽著老婆滿街逛

            嚴以律己,寬以待人. 三思而后行.
            GMail/GTalk: yanglinbo#google.com;
            MSN/Email: tx7do#yahoo.com.cn;
            QQ: 3 0 3 3 9 6 9 2 0 .

            通過異步程序調用(APC)實現的定時功能

            轉載自:http://www.vckbase.com/document/viewdoc/?id=1587

            編譯:張海粟

              定時器是一個在特定時間或者規則間隔被激發的內核對象。結合定時器的異步程序調用可以允許回調函數在任何定時器被激發的時候執行。本文的例子代碼顯示了如何實現。
              使用本定時器時,你需要把常量_WIN32_WINNT定義為0x0400,并且此常量應該在包之前定義,以確保聲明合適的定時器原型函數。
              通過調用CreateWaitableTimer()可以創建一個定時器,此函數返回一個指向內核對象的句柄。若定時器已經存在,你可以通過使用OpenWaitableTimer()獲得一個進程相關的句柄。無論是通過CreateWaitableTimer() 還是通過OpenWaitableTimer()獲得的句柄,在不需要定 時器時必須釋放,方法是使用函數CloseHandle()。
              定時的時間通過調用SetWaitableTimer()來設置,可以設置為一個特定的時刻(如December 16, 1999 at 9:45 PM)或者一個相對的時間(如從現在起每五分鐘)。函數SetWaitableTime()定時的時間參數要求LARGE_INTEGER類型。這個值應該符合在結構體FILETIME中描述的格式。如果值是正的,代表一個特定的時刻。如果值是負的,代表以100納秒為單位的相對時間。后面的示例代碼中使用的是相對時間。在調用SetWaitableTimer()函數后,定時器將在每5秒被激發一次。
              你也可以將定時器設置為周期性的自我激發,方法是向SetWaitableTimer()的第三個參數傳遞一個周期參數(以毫秒為單位)。在CreateWaitableTimer()的第二個參數傳遞FALSE可以產生一個自動歸零的定時器。本例設置周期為兩秒的定時器。
              當設置了定時器之后,你就可以將APC與其結合起來。這里把APC函數稱作完全例程。完全例程的地址作為SetWaitableTimer()的第四個參數。第五個參數是一個空類型的指針,你可以使用它來傳遞完全例程的參數。
              在所有的APC中,要執行一個完全例程則線程必須處于監聽狀態。完全例程將總是被調用SetWaitableTimer()的相同的線程執行,所以此線程必須將必須其自身置于監聽狀態。可以調用下面的任何一個監聽函數來完成監聽狀態的設置:

            • SleepEx();
            • WaitForSingleObjectEx();
            • WaitForMultipleObjectsEx();
            • MsgWaitForMultipleObjectsEx();
            • SignalObjectAndWait();

              任何一個線程都有一個APC隊列。在調用上面的任何一個函數時,如果線程的APC隊列中有實體,則此線程不會進入休眠狀態,取而代之要做的是將實體從APC隊列中取出,然后調用相應的完全例程。
              如果在APC隊列中不存在實體,那么線程將會被掛起,直至等待條件滿足為止。滿足等待條件的有:一個實體加入到APC隊列中,超時,激活句柄等,以及在調用MsgWaitForMultipleObjectsEx()情況下,一個消息進入到線程的一個消息隊列中。若等待條件滿足的是APC隊列中的一個實體,那么線程會被激活,并且執行完全例程,這種情況下的函數的返回值是 WAIT_IO_COMPLETION.

            【重要提示】

            1、在執行完一個完全例程之后,系統會檢查在APC中剩下的實體以處理。一個監視函數僅僅在處理完所有APC實體后才返回。因此,如果實體加入到APC隊列的速度比處理的更快的話,則調用這些函數可能永遠也不能返回。特別當定時等待的時間比起要求執行完全例程的時間更短的話,這種情況更容易發生。 
            2、當使用APC來實現定時器時,設置定時的線程不應該等待定時器的句柄。如果等待定時器的句柄的話,則喚起這個線程的原因是定時器被激活,而不是有實體加入到APC隊列中。這時線程將不再處于監聽狀態,所以完全例程也不會被調用。在本例中,Sleep()被用于將線程置于監聽狀態。在定時器激活后,如果有實體被加入到此線程的APC隊列中時,Sleep()就會喚醒此線程。

            【示例代碼】

            #define _WIN32_WINNT 0x0500

            #include 
            <windows.h>
            #include 
            <stdio.h>

            #define _SECOND 10000000

            typedef 
            struct _MYDATA {
               TCHAR 
            *szText;
               DWORD dwValue;
            }
             MYDATA;

            VOID CALLBACK TimerAPCProc(
               LPVOID lpArg,               
            // Data value
               DWORD dwTimerLowValue,      // Timer low value
               DWORD dwTimerHighValue )    // Timer high value

            {
               MYDATA 
            *pMyData = (MYDATA *)lpArg;

               printf( 
            "Message: %s\nValue: %d\n\n", pMyData->szText,
                      pMyData
            ->dwValue );
               MessageBeep(
            0);

            }


            void main( void ) 
            {
               HANDLE          hTimer;
               BOOL            bSuccess;
               __int64         qwDueTime;
               LARGE_INTEGER   liDueTime;
               MYDATA          MyData;
               TCHAR           szError[
            255];

               MyData.szText 
            = "This is my data.";
               MyData.dwValue 
            = 100;

               
            if ( hTimer = CreateWaitableTimer(
                       NULL,                   
            // Default security attributes
                       FALSE,                  // Create auto-reset timer
                       "MyTimer" ) )           // Name of waitable timer
               {
                  __try 
                  
            {
                     
            // Create an integer that will be used to signal the timer 
                     
            // 5 seconds from now.
                     qwDueTime = -5 * _SECOND;

                     
            // Copy the relative time into a LARGE_INTEGER.
                     liDueTime.LowPart  = (DWORD) ( qwDueTime & 0xFFFFFFFF );
                     liDueTime.HighPart 
            = (LONG)  ( qwDueTime >> 32 );

                     bSuccess 
            = SetWaitableTimer(
                        hTimer,           
            // Handle to the timer object
                        &liDueTime,       // When timer will become signaled
                        2000,             // Periodic timer interval of 2 seconds
                        TimerAPCProc,     // Completion routine
                        &MyData,          // Argument to the completion routine
                        FALSE );          // Do not restore a suspended system

                     
            if ( bSuccess ) 
                     
            {
                        
            for ( ; MyData.dwValue < 1000; MyData.dwValue += 100 ) 
                        
            {
                           SleepEx(
                              INFINITE,     
            // Wait forever
                              TRUE );       // Put thread in an alertable state
                        }


                     }
             
                     
            else 
                     
            {
                        wsprintf( szError, 
            "SetWaitableTimer failed with Error \
                           %d.", GetLastError() );
                        MessageBox( NULL, szError, "Error", MB_ICONEXCLAMATION );
                     }


                  }
             
                  __finally 
                  
            {
                     CloseHandle( hTimer );
                  }

               }
             
               
            else 
               
            {
                  wsprintf( szError, 
            "CreateWaitableTimer failed with Error %d."
                      GetLastError() );
                  MessageBox( NULL, szError, 
            "Error", MB_ICONEXCLAMATION );
               }

            }

             

             

            原文參考:Using a Waitable Timer with an Asynchronous Procedure Call

            posted on 2011-06-02 17:15 楊粼波 閱讀(707) 評論(0)  編輯 收藏 引用

            狠狠狠色丁香婷婷综合久久五月| 2021国产成人精品久久| 亚洲婷婷国产精品电影人久久| 久久AⅤ人妻少妇嫩草影院| 伊人伊成久久人综合网777| 久久精品国产亚洲精品2020| 久久九九有精品国产23百花影院| 久久93精品国产91久久综合| 丁香色欲久久久久久综合网| 99re这里只有精品热久久| 亚洲а∨天堂久久精品| 精品人妻久久久久久888| 人人狠狠综合久久亚洲高清| 午夜精品久久久久久毛片| 中文字幕成人精品久久不卡| 日韩乱码人妻无码中文字幕久久| 国产精品无码久久久久久| 国产免费久久精品99re丫y| 精品久久久久久中文字幕| 亚洲国产另类久久久精品小说 | 一极黄色视频久久网站| 99久久er这里只有精品18| 色综合久久夜色精品国产| 久久综合久久综合九色| 亚洲国产精品无码久久一区二区 | 国产999精品久久久久久| 免费无码国产欧美久久18| 久久国产美女免费观看精品 | 精品少妇人妻av无码久久| 亚洲午夜无码久久久久| 精品国产乱码久久久久软件| 精品久久久久久国产牛牛app| 久久国产乱子伦免费精品| 99久久做夜夜爱天天做精品| 精品久久久久久99人妻| 精品久久久久久无码国产| 大蕉久久伊人中文字幕| 国产精品伦理久久久久久| 精品国产乱码久久久久久浪潮| 99久久伊人精品综合观看| 久久99国产一区二区三区|