Jak wstrzymać wykonywanie kodu na kilka sekund?

przez | 2024-11-09

Czasami piszemy jakiś kod i chcemy zatrzymać wykonywanie aplikacji na określony czas. Np. nasza aplikacja uruchamia jakiś zewnętrzny program i nie chcemy aby następne instrukcje wykonały się od razu, tylko po pewnym czasie (np. jak uruchomiona przez nas zewnętrzna aplikacja się wykona i zwróci wynik w postaci utworzonego pliku).

Uwaga: zakładanie na sztywno, że wstrzymanie wykonywania aplikacji na 5 sekund wystarczy, aby zewnętrzna aplikacja zdążyła „wykonać swoją robotę” jest zgubne. W przypadku różnych niekorzystnych zjawisk (wolny komputer, chwilowe przeciążenie CPU) może  spowodować, że owy zewnętrzny program który uruchomiliśmy, nie wyrobi się w 5 sekund. Tutaj dobrze by było opakować nasze opóźnienie w jakąś pętlę typu Do while, która opóźnia wykonanie naszego programu o 1 sekundę ale dodatkowo sprawdza, czy owy plik już powstał i jeśli nie, to nadal czeka.

Najprostszy sposób (ale działa tylko w VBA dla Excela) to wywołanie metody Application.Wait. Oto prosty przykład:

Sub Pauza5s()
    Debug.Print "Uruchomienie aplikacji o godzinie " & Now()
    Application.Wait Now + TimeValue("00:00:05")
    Debug.Print "Powrót do świata żywych po 5 sekundach " & Now()
End Sub 

To rozwiązanie ma dwie wady. Po pierwsze: nie działa np. dla VBA dla Worda. Druga wada jest taka, że „rozdzielczość” to zaledwie 1 sekunda. Jeśli chcesz użyć mniejszego opóźnienia (np. 0,1 sekundy) to musimy skorzystać z innego rozwiązania np. wywołać odpowiednią funkcję WinAPI.

#If VBA7 Then
    Declare PtrSafe Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
#Else
    Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
#End If
Sub Pauza100ms()
    Debug.Print "Uruchomienie aplikacji o godzinie " & Now()
    Sleep 100
    Debug.Print "Powrót do świata żywych po 0.1 s " & Now()
End Sub

Tutaj rozdzielczość jest większa, bo teoretycznie wynosi aż 1 ms (1 sekunda = 1000 ms), ale funkcja ta nie nadaje się jeśli chcesz precyzyjnie wstrzymać wykonanie programu na baaardzo krótkie okresy czasu (sam narzut wynikający z wywołania funkcji API jest większy niż 1 ms). U mnie 1000 krotne wywołanie funkcji Sleep 1 trwało aż 16 sekund!

Uwaga: Oba te sposoby całkowicie wstrzymują wykonywanie programu. Jeśli użytkownik klika w przycisk, który wywołuje funkcję w której jest instrukcja Sleep (albo Application.Wait) to na czas wstrzymania wykonywania programu aplikacja nie reaguje na zdarzenia (nawet na tak prozaiczne rzeczy, jak np. przesunięcie okna UserForm).

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany. Wymagane pola są oznaczone *

Witryna wykorzystuje Akismet, aby ograniczyć spam. Dowiedz się więcej jak przetwarzane są dane komentarzy.