DoEvents ist dafür da, die Kontrolle ans Betriebssystem zurück zu geben, um asynchrone Ereignisse wie Maus- und TastaturEvents zu verarbeiten. Wenn dein StackTest noch nicht zu Ende gelaufen ist und du "mittendrin" in deine Button Ereignisprozedur springst, ist damit StackTest unterbrochen und wird erst wieder weiterlaufen, nachdem Command1_Click fertig ist. Das wird aber niemals fertig, da StackTest nicht in der Lage ist - weil unterbrochen - das RunningFlag auf False zu setzen.
Entweder beschäftigst du dich mit Threads oder du änderst dein Design.
Packe mal folgende Zeilen in deinen Button-Handler und die Funktion TestStack Static Indent As Integer
Indent = Indent + 1
Debug.Print String(c_IND * Indent, ">") & " Command1_Click" 'bzw. testStack
'Hier kommt der Code
Debug.Print String(c_IND * Indent, "<") & " Command1_Click"
Indent = Indent - 1 Hier kannst du sehr gut die Aufruf-Hierachie an den Printouts nachvollziehen. Du wirst also feststellen, das der Aufruf von TestStack synchrin erfolgt, dass heißt, du kommst erst in deinen Button-Handler zurück, wenn TestStack fertig ist. Der wird aber nicht fertig, weil du die while-loop im zweiten Aufruf von Command1_Click nudelt.
Ich stelle mir daher folgende Lösung vor:
Option Explicit
Private Const c_IND As Integer = 3
Private m_Break As Boolean
Private m_NeuAuftrag As Boolean
Private m_IsAuftragRunning As Boolean
Private m_CloseApp As Boolean
Private Sub Command1_Click()
Static Indent As Integer
Indent = Indent + 1
Debug.Print String(c_IND * Indent, ">") & " Command1_Click"
If m_IsAuftragRunning Then
m_Break = True
m_NeuAuftrag = True
End If
Timer.Interval = 1
Timer.Enabled = True
Debug.Print String(c_IND * Indent, "<") & " Command1_Click"
Indent = Indent - 1
End Sub
Private Sub test()
Dim i As Long
Static Indent As Integer
Indent = Indent + 1
Debug.Print String(c_IND * Indent, ">") & " test"
For i = 1 To 1000000
If i Mod 10 = 0 Then
If m_Break Then
Debug.Print String(c_IND * (Indent + 1), ".") & " BREAK-->"
Exit For
End If
Label1.Caption = CStr(i)
DoEvents
End If
Next i
If Not m_Break Then Debug.Print String(c_IND * (Indent + 1), ".") & " MADE IT" & _
"!!!"
Debug.Print String(c_IND * Indent, "<") & " test"
Indent = Indent - 1
End Sub
Private Sub Form_Load()
m_Break = False
Timer.Interval = 1
Timer.Enabled = False
m_NeuAuftrag = False
m_IsAuftragRunning = False
m_CloseApp = False
End Sub
Private Sub Form_QueryUnload(Cancel As Integer, UnloadMode As Integer)
m_Break = True
m_NeuAuftrag = False
m_CloseApp = True
If m_IsAuftragRunning Then
Cancel = 1
End If
End Sub
Private Sub Timer_Timer()
Static Indent As Integer
Indent = Indent + 1
Debug.Print String(c_IND * Indent, ">") & " Timer_Timer"
Timer.Interval = 500
If m_IsAuftragRunning Then
Timer.Enabled = False
Else
m_IsAuftragRunning = True
test
m_IsAuftragRunning = False
If m_CloseApp Then
SendKeys "%{F4}", False
DoEvents
End If
If m_NeuAuftrag And m_Break Then
m_NeuAuftrag = False
Timer.Enabled = True
Else
Timer.Enabled = False
End If
m_Break = False
End If
Debug.Print String(c_IND * Indent, "<") & " Timer_Timer"
Indent = Indent - 1
End Sub Bei mir scheint's zumindest zu funktionieren. Jetzt schreibst du, dass da irgendwo noch ganz viel Code kommt. Grundsätzlich ungünstig viel Code in einer Ereignisprozedur zu haben. Besser auslagern in eine Sub/Funktion. Du kannst ja nun noch ein Flag setzen, dass TestStack oder hier test es gemacht hat und dann entsprechend den Code ablaufen lassen.
Ich denke ohne Timer kriegste das nicht hin. Denn du willst ja so eine Art Threading erreichen. App beenden bzw. Form schließen habe ich noch extra verarbeitet.
Gruß
Dirk
--
?Get it right the first time  |