在VB語言中,DOEVENTS的具體的用法和含義


DoEvents的應用及注意事項 

轉讓控制權,以便讓操作系統處理其它的事件。

DoEvents 函數會返回一個 Integer,以代表 Visual Basic 獨立版本中打開的窗體數目,例如,Visual Basic,專業版,在其它的應用程序中,DoEvents 返回 0。

DoEvents 會將控制權傳給操作系統。當操作系統處理完隊列中的事件,並且在 SendKeys 隊列中的所有鍵也都已送出之后,返回控制權。

DoEvents 對於簡化諸如允許用戶取消一個已啟動的過程 — 例如搜尋一個文件 — 特別有用。對於長時間過程,放棄控制權最好使用定時器或通過委派任務給 ActiveX EXE 部件來完成。以后,任務還是完全獨立於應用程序,多任務及時間片由操作系統來處理。

小心 確保以 DoEvents 放棄控制權的過程,在第一次 DoEvents 返回之前,不能再次被其他部分的代碼調用;否則會產生不可預料的結果。此外,如果其它的應用程序可能會和本過程以不可預知的方式進行交互操作,那么也不要使用 DoEvents,因為此時不能放棄控制權。

使用 DoEvents

盡管 Timer 事件是后台處理的最好工具,對耗時極多的任務,情況更是如此,但是,DoEvents 函數還是提供了一種取消任務的簡便方法。例如,下列代碼將顯示一個 "Process" 按鈕,單擊這個按鈕時,它將變成 "Cancel" 按鈕。再次單擊按鈕又將中斷正在執行的任務。

'此按鈕標題是 "Process"
Private Sub Command1_Click()
'過程的所有實例都共享靜態變量。
  Static blnProcessing As Boolean
  Dim lngCt As Long
  Dim intYieldCt As Integer
  Dim dblDummy As Double
  '按下按鈕時,檢測是否在處理
  If blnProcessing Then
   '如果正在處理,則取消
      blnProcessing = False
  Else
      Command1.Caption = "Cancel"
      blnProcessing = True
      lngCt = 0
   '執行一百萬次浮點乘法計算。每一千次后,檢測是否要取消。
      Do While blnProcessing And (lngCt < 1000000)
        For intYieldCt = 1 To 1000
            lngCt = lngCt + 1
            dblDummy = lngCt * 3.14159
        Next intYieldCt
      'DoEvents 語句允許其它事件發生,包括第二次按此按鈕。
        DoEvents
      Loop
      blnProcessing = False
      Command1.Caption = "Process"
      MsgBox lngCt & " multiplications were performed"
  End If
End Sub

DoEvents 將控制切換到操作環境內核。只要此環境中的所有應用程序都有機會響應待處理事件,應用程序就又恢復控制。這不會使應用程序放棄焦點,但會使后台事件能夠得到處理。

這種妥協的結果可能並不總是達到預期目標。例如,下述 Click 事件代碼在單擊按鈕后要一直等候十秒鍾,而后才顯示一條信息。如果在按鈕正在等待期間單擊它,則將以相反順序完成單擊操作。

Private Sub Command2_Click()
  Static intClick As Integer
  Dim intClickNumber As Integer
  Dim dblEndTime As Double
      '每次單擊按鈕時
      '賦予唯一數值。
  intClick = intClick + 1
  intClickNumber = intClick
      '等待十秒。
  dblEndTime = Timer + 10#
  Do While dblEndTime > Timer
      '不做任何事情,僅僅允許
      '其它應用程序處理
      '它們的事件。
      DoEvents
  Loop
  MsgBox "Click " & intClickNumber & " is finished"
End Sub

對於通過 DoEvents 放棄控制的事件過程,有時可能希望防止在 DoEvents 返回之前重新調用這一過程。否則將無窮無盡地調用該過程,直到系統資源消耗殆盡。可暫時禁止控件,或象上例一樣,使用一個靜態的“標志”變量防止此事發生。

在使用全局數據時避免 DoEvents
當一個函數已通過 DoEvents 放棄控制時,可相當安全地再次調用函數。例如,下一過程將檢測質數並用 DoEvents 語句周期地啟動其它應用程序處理事件:

Function PrimeStatus (TestVal As Long) As Integer
  Dim Lim As Integer
  PrimeStatus = True
  Lim = Sqr(TestVal)
  For I = 2 To Lim
      If TestVal Mod I = 0 Then
        PrimeStatus = False
        Exit For
      End If
      If I Mod 200 = 0 Then DoEvents
  Next I
End Function

該代碼中每重復 200 次就調用一次 DoEvents 語句。這樣一來,當該環境的其余部分對事件作出響應時,只要有必要,PrimeStatus 過程就可繼續計算。

考慮在調用 DoEvents 期間發生的事情。在其它窗體和應用程序處理事件時將暫停執行應用程序代碼。這些事件之一有可能是一個按鈕單擊操作,它將再次啟動 PrimeStatus 過程。

這將導致重新進入 PrimeStatus 過程的,但是,因為在函數每次出現時,堆棧都為其參數和局部變量分配了空間,所以重入不會引發沖突。當然,如果過多調用 PrimeStatus,則可能出現“溢出堆棧空間”錯誤。

如果 PrimeStatus 使用或改變模塊級變量或全局數據,情況就會完全不同。此時,在 DoEvents 能夠返回之前執行 PrimeStatus 的另一個實例,這將導致模塊數據或全局數據的值完全不同於它們在調用 DoEvents 之前的值。於是,PrimeStatus 的結果將會難以預料。

VB中DoEvents的注意事項

對與再大循環里 加入   DoEvents卻是可以使應用程序響應其他程序,但是 DoEvents也會很大程度上影響循環的速度,所以一般情況我這樣用

If GetInputState Then DoEvents

雖然多了個判斷語句,但速度上確快了很多

比較以下代碼代碼就知道了速度的差別

Private Declare Function GetInputState Lib "user32" () As Long

Private Declare Function GetTickCount Lib "kernel32" () As Long

Private Sub Command1_Click()

      Dim s As Long

      s = GetTickCount

      For i = 1 To 1000000

          DoEvents

      Next

      MsgBox GetTickCount - s

End Sub

Private Sub Command2_Click()

      Dim s As Long

      s = GetTickCount

      For i = 1 To 1000000

          If GetInputState Then DoEvents

      Next

      MsgBox GetTickCount - s

End Sub


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM