文章編號: 231298 - 上次校閱: 2004年7月13日 - 版次: 3.1

如何使用與 Visual Basic SetWaitableTimer

系統提示本文適用於您使用的作業系統之外的作業系統。與您不相關的文章內容已停用。

在此頁中

全部展開 | 全部摺疊

結論

許多程式設計人員使用睡眠 API 函數來暫停程式執行。其中一個使用睡眠的缺點是它會暫停應用程式正在執行中,執行緒和重新應用程式有開啟任何視窗將不繪製正確。這可能會對使用者顯示 unattractive 使用者介面。睡眠的替代方法是使用 SetWaitableTimer 這將允許螢幕重繪、 接收 DDE 訊息等等。

其他相關資訊

下列程式碼範例會說明如何 SetWaitableTimer API 使用。

雖說是逐步範例

  1. 在 Visual Basic 中啟動新的標準 EXE 專案。預設會建立 Form1。
  2. 在 Form1 上放置兩個 CommandButtons
  3. 將下列程式碼貼到 Form1 的程式碼模組:
    Option Explicit
    
    ' Sleep API is declared in the form to keep the
    ' SetWaitableTimer code in its own re-usable module.
    Private Declare Sub Sleep Lib "kernel32" ( _
        ByVal dwMilliseconds As Long)
    
    Private Sub Command1_Click()
        Command1.Enabled = False
        Wait 10 ' seconds
        Command1.Enabled = True
    End Sub
    
    Private Sub Command2_Click()
        Command2.Enabled = False
        Sleep 10000 ' milliseconds
        Command2.Enabled = True
    End Sub
    
    Private Sub Form_Load()
        With Form1
            .Height = 1400
            .Width = 2400
        End With
        With Command1
            .Move 100, 100, 2000, 300
            .Caption = "SetWaitableTimer"
        End With
        With Command2
            .Move 100, 500, 2000, 300
            .Caption = "Sleep"
        End With
    End Sub
    					
  4. 從 [專案] 功能表中,按一下 [加入模組],以將新的模組 (Module1) 加入至專案]。
  5. 下列程式碼貼到 Module1 中:
    Option Explicit
    
    Private Type FILETIME
        dwLowDateTime As Long
        dwHighDateTime As Long
    End Type
    
    Private Const WAIT_ABANDONED& = &H80&
    Private Const WAIT_ABANDONED_0& = &H80&
    Private Const WAIT_FAILED& = -1&
    Private Const WAIT_IO_COMPLETION& = &HC0&
    Private Const WAIT_OBJECT_0& = 0
    Private Const WAIT_OBJECT_1& = 1
    Private Const WAIT_TIMEOUT& = &H102&
    
    Private Const INFINITE = &HFFFF
    Private Const ERROR_ALREADY_EXISTS = 183&
    
    Private Const QS_HOTKEY& = &H80
    Private Const QS_KEY& = &H1
    Private Const QS_MOUSEBUTTON& = &H4
    Private Const QS_MOUSEMOVE& = &H2
    Private Const QS_PAINT& = &H20
    Private Const QS_POSTMESSAGE& = &H8
    Private Const QS_SENDMESSAGE& = &H40
    Private Const QS_TIMER& = &H10
    Private Const QS_MOUSE& = (QS_MOUSEMOVE _
                                Or QS_MOUSEBUTTON)
    Private Const QS_INPUT& = (QS_MOUSE _
                                Or QS_KEY)
    Private Const QS_ALLEVENTS& = (QS_INPUT _
                                Or QS_POSTMESSAGE _
                                Or QS_TIMER _
                                Or QS_PAINT _
                                Or QS_HOTKEY)
    Private Const QS_ALLINPUT& = (QS_SENDMESSAGE _
                                Or QS_PAINT _
                                Or QS_TIMER _
                                Or QS_POSTMESSAGE _
                                Or QS_MOUSEBUTTON _
                                Or QS_MOUSEMOVE _
                                Or QS_HOTKEY _
                                Or QS_KEY)
    
    Private Declare Function CreateWaitableTimer Lib "kernel32" _
        Alias "CreateWaitableTimerA" ( _
        ByVal lpSemaphoreAttributes As Long, _
        ByVal bManualReset As Long, _
        ByVal lpName As String) As Long
        
    Private Declare Function OpenWaitableTimer Lib "kernel32" _
        Alias "OpenWaitableTimerA" ( _
        ByVal dwDesiredAccess As Long, _
        ByVal bInheritHandle As Long, _
        ByVal lpName As String) As Long
        
    Private Declare Function SetWaitableTimer Lib "kernel32" ( _
        ByVal hTimer As Long, _
        lpDueTime As FILETIME, _
        ByVal lPeriod As Long, _
        ByVal pfnCompletionRoutine As Long, _
        ByVal lpArgToCompletionRoutine As Long, _
        ByVal fResume As Long) As Long
        
    Private Declare Function CancelWaitableTimer Lib "kernel32" ( _
        ByVal hTimer As Long)
        
    Private Declare Function CloseHandle Lib "kernel32" ( _
        ByVal hObject As Long) As Long
        
    Private Declare Function WaitForSingleObject Lib "kernel32" ( _
        ByVal hHandle As Long, _
        ByVal dwMilliseconds As Long) As Long
        
    Private Declare Function MsgWaitForMultipleObjects Lib "user32" ( _
        ByVal nCount As Long, _
        pHandles As Long, _
        ByVal fWaitAll As Long, _
        ByVal dwMilliseconds As Long, _
        ByVal dwWakeMask As Long) As Long
    
    Public Sub Wait(lNumberOfSeconds As Long)
        Dim ft As FILETIME
        Dim lBusy As Long
        Dim lRet As Long
        Dim dblDelay As Double
        Dim dblDelayLow As Double
        Dim dblUnits As Double
        Dim hTimer As Long
        
        hTimer = CreateWaitableTimer(0, True, App.EXEName & "Timer")
        
        If Err.LastDllError = ERROR_ALREADY_EXISTS Then
            ' If the timer already exists, it does not hurt to open it
            ' as long as the person who is trying to open it has the
            ' proper access rights.
        Else
            ft.dwLowDateTime = -1
            ft.dwHighDateTime = -1
            lRet = SetWaitableTimer(hTimer, ft, 0, 0, 0, 0)
        End If
        
        ' Convert the Units to nanoseconds.
        dblUnits = CDbl(&H10000) * CDbl(&H10000)
        dblDelay = CDbl(lNumberOfSeconds) * 1000 * 10000
        
        ' By setting the high/low time to a negative number, it tells
        ' the Wait (in SetWaitableTimer) to use an offset time as
        ' opposed to a hardcoded time. If it were positive, it would
        ' try to convert the value to GMT.
        ft.dwHighDateTime = -CLng(dblDelay / dblUnits) - 1
        dblDelayLow = -dblUnits * (dblDelay / dblUnits - _
            Fix(dblDelay / dblUnits))
        
        If dblDelayLow < CDbl(&H80000000) Then
            ' &H80000000 is MAX_LONG, so you are just making sure
            ' that you don't overflow when you try to stick it into
            ' the FILETIME structure.
            dblDelayLow = dblUnits + dblDelayLow
            ft.dwHighDateTime = ft.dwHighDateTime + 1 
        End If 
        
        ft.dwLowDateTime = CLng(dblDelayLow)
        lRet = SetWaitableTimer(hTimer, ft, 0, 0, 0, False)
        
        Do
            ' QS_ALLINPUT means that MsgWaitForMultipleObjects will
            ' return every time the thread in which it is running gets
            ' a message. If you wanted to handle messages in here you could,
            ' but by calling Doevents you are letting DefWindowProc
            ' do its normal windows message handling---Like DDE, etc.
            lBusy = MsgWaitForMultipleObjects(1, hTimer, False, _
                INFINITE, QS_ALLINPUT&)
            DoEvents
        Loop Until lBusy = WAIT_OBJECT_0
        
        ' Close the handles when you are done with them.
        CloseHandle hTimer
    
    End Sub
    					
  6. 執行專案。
  7. 按一下 [睡眠] 按鈕。雖然應用程式在休眠狀態,請注意並不重繪螢幕 (拖曳頂端的應用程式的另一個視窗,然後將其拖曳離開)。然後,嘗試與 SetWaitableTimer 按鈕相同的測試。

?考

如需詳細資訊按一下面的文件編號,檢視 「 Microsoft 知識庫 」 中的發行項:
184796? (http://support.microsoft.com/kb/184796/EN-US/ ) 如何以非同步的程序呼叫使用 waitable 計時器
Microsoft Win32 軟體開發人員套件的文件 SetWaitableTimer]、 [MsgWaitForMultipleObjects] 和 [CloseHandle API 呼叫。

這篇文章中的資訊適用於:
  • Microsoft Visual Basic 5.0 Learning Edition
  • Microsoft Visual Basic 6.0 Learning Edition
  • Microsoft Visual Basic 5.0 Professional Edition
  • Microsoft Visual Basic 6.0 Professional Edition
  • Microsoft Visual Basic 5.0 Enterprise Edition
  • Microsoft Visual Basic Enterprise Edition for Windows 6.0
  • Microsoft Visual Basic 4.0 Professional Edition
關鍵字:?
kbmt kbapi kbhowto KB231298 KbMtzh
機器翻譯機器翻譯
重要:本文是以 Microsoft 機器翻譯軟體翻譯而成,而非使用人工翻譯而成。Microsoft 同時提供使用者人工翻譯及機器翻譯兩個版本的文章,讓使用者可以依其使用語言使用知識庫中的所有文章。但是,機器翻譯的文章可能不盡完美。這些文章中也可能出現拼字、語意或文法上的錯誤,就像外國人在使用本國語言時可能發生的錯誤。Microsoft 不為內容的翻譯錯誤或客戶對該內容的使用所產生的任何錯誤或損害負責。Microsoft也同時將不斷地就機器翻譯軟體進行更新。
按一下這裡查看此文章的英文版本:231298? (http://support.microsoft.com/kb/231298/en-us/ )
Microsoft及(或)其供應商不就任何在本伺服器上發表的文字資料及其相關圖表資訊的恰當性作任何承諾。所有文字資料及其相關圖表均以「現狀」供應,不負任何擔保責任。Microsoft及(或)其供應商謹此聲明,不負任何對與此資訊有關之擔保責任,包括關於適售性、適用於某一特定用途、權利或不侵權的明示或默示擔保責任。Microsoft及(或)其供應商無論如何不對因或與使用本伺服器上資訊或與資訊的實行有關而引起的契約、過失或其他侵權行為之訴訟中的特別的、間接的、衍生性的損害或任何因使用而喪失所導致的之損害、資料或利潤負任何責任。