Can I trust in this function?
Goodmorning :)
I need in one of my projects to use the DoEvents statement. Many programmers said me that is not a good way use it for vary reasons, but as I need it into a function, I thought that there might be another better solution. With a Google query, I found this code:
Code:
Option Explicit
Private Type POINTAPI
x As Long
y As Long
End Type
Private Type MSG
hwnd As Long 'hwnd della finestra di destinazione del messaggio
message As Long 'numero che identifica il tipo di messaggio
wParam As Long 'parametro del messaggio (tipo e valore cambiano in funzione del tipo di messaggio inviato)
lParam As Long 'altro parametro del messaggio che varia sempre in funzione del messaggio
time As Long 'l'ora in cui รจ stato inviato il messaggio
pt As POINTAPI 'posizione del cursore al momento dell'invio del messaggio
End Type
'La funzione PeekMessage cerca e recupera un messaggio in coda e lascia immediatamente il controllo al programma
'Se il messaggio viene recuperato la funzione restituisce TRUE, in caso contrario restituisce FALSE.
'La funzione prevede un parametro (wRemoveMsg) che indica se rimuovere il messaggio recuperato dalla coda o di lasciarlo dove si trova.
Private Declare Function PeekMessage Lib "user32" Alias "PeekMessageA" ( _
lpMsg As MSG, _
ByVal hwnd As Long, _
ByVal wMsgFilterMin As Long, _
ByVal wMsgFilterMax As Long, _
ByVal wRemoveMsg As Long) As Long
Private Const PM_REMOVE = &H1 'indica alla funzione PeekMessage di rimuovere il messaggio in coda
'La funzione TranslateMessage codifica alcuni messaggi arrivati dalla tastiera in modo da renderli opportunamente eleborabili.
Private Declare Function TranslateMessage Lib "user32" (lpMsg As MSG) As Long
'La funzione DispatchMessage richiama la corretta procedura che deve elaborare il messaggio in base al valore del campo hwnd della struttura MSG
'N.B.: l'omissione di questa funzione porterebbe alla mancata elaborazione dei messaggi e, quindi, al probabile blocco del sistema.
Private Declare Function DispatchMessage Lib "user32" Alias "DispatchMessageA" (lpMsg As MSG) As Long
Private Const lMaxCounter As Long = 100000
Private Sub MyDoEvents() 'funzione alternativa alla funzione di VB "DoEvents"
Dim CurrMsg As MSG
'Questo loop recupera (e cancella) tutti i messaggi dalla coda e li invia alla finestra di destinazione
Do While PeekMessage(CurrMsg, 0, 0, 0, PM_REMOVE) <> 0
TranslateMessage CurrMsg
DispatchMessage CurrMsg
Loop
End Sub
It seems work well and faster than the DoEvents statement. But can I really trust in this code lines? Can I be sure that if I replace all the DoEvents calls with MyDoEvents any problems won't be raised?
Thank you for all your opinions and suggestions,
:wave:
Re: Can I trust in this function?
If it ain't broke, don't fix it.
I do not sprinkle DoEvents everywhere.
But if I see something is 'living in the past', and the controls Refresh command does not help, then it cops a DoEvents.
I reckon if you are judicious about your use of DoEvents, just stick with that.
Rob
PS I will be getting donations from the other post that I just made, so that will help build a fund, in case anyone sues me over this advice.
Re: Can I trust in this function?
It appears that the code you found originated from NirSoft's DoEvents alternative function. It also looks like somebody else downloaded the same code and has asked the same question as you did in the "MyDoEvents" vs DoEvents? thread. There were 16 responses in that thread so far.
Re: Can I trust in this function?
I don't remember what the source was and I didn't know there already was a thread like this. However, reading the answers, I think that I should continue to use the VB's DoEvents statement.
Thanks,
:wave:
Re: Can I trust in this function?
The DoEvents() function lived on in VB6 for a reason, sometimes it is necessary.
However most of the reasons people use it are incorrect. It is only really safe in certain circumstances for a few specific purposes. Because a newb will reach for it far too often (and then come back posting a question about why their programs blow up, lose data, corrupt data, etc.) a DoEvents is evil mantra came about.
The VB6 manuals (and the soft copy contained in the MSDN Library CDs providing VB6's online Help) discuss DoEvents and the preferred alternatives in several chapters.
So choosing whether to use it or not depends entirely on where and why you are considering using it. There is no simple answer, and why would you expect there to be one? Programming isn't a cookbook endeavor.
Re: Can I trust in this function?
I use DoEvents in several cases, i.e. into a Delay function (to let a fluid refresh or to allow users to move the Form) or to stop a loop with a click on a button, but more in general, I use it when I don't want that a long operation (once launched) monopolizes my project.
My question is more about to know if there is a way to emulate DoEvents statement avoiding a code come-back. Try this code:
Code:
Private Sub Delay(ByVal Seconds As Single)
Seconds = (Timer + Seconds)
Do While Timer < Seconds
DoEvents
Loop
End Sub
Private Sub Quit()
Dim f As Form
For Each f In Forms
Unload f
Next f
End Sub
Private Sub Form_Load()
Me.Show
Me.Refresh
Delay 10
MsgBox "App slept for 2 seconds"
End Sub
Private Sub Command1_Click()
Quit
End If
If you click on the command button before MsgBox appears, the form won't be unloaded and it still remains into the running processes. And this is not good. The only way to escape is to use End to finish the app. But if I need only to close one form, calling End statement will close the whole program.
Don't tell me to use a Timer control instead, because into unless loops neither Timer's ticks are fired if you don't put (into the loop) a DoEvents.
Re: Can I trust in this function?
Did you know that DoEvents is a very Frequently Asked Question? Searching this forum alone turned up 180 hits. In fact, in this recent thread, two methods were proposed that eventually led to the resolution of the nested looping problem. Your given example is a simpler form of the problem discussed there, namely, unloading a Form while in the middle of a loop (made possible by use of DoEvents). The Interrupting Background Processing article talks about ways of implementing long-running tasks.
Re: Can I trust in this function?
I would not be messing around in the Form_Load event.
Re: Can I trust in this function?
I thought the title of this thread was clear enough... I didn't want to know about VB's DoEvents function. My question was (and is still now): the code I posted, is it 100% safe? Does it really do all it promises to do (run faster than DoEvents function and let OS to process all messages)?
About the speediness, that's true: MyDoEvents function is faster. But what about the else? Does it really processess all the messages? After I've read this thread, I think to have understood that MyDoEvents runs my own thread messages only (and if it so, that's how it runs faster than DoEvents, which has to manage all system messages). Now, if this is right, I think that there surely are unexpected effects if something goes wrong.
And that's all, there's nothing else that I wanted to know.
Re: Can I trust in this function?
I think the deeper issue is, why do you need to use DoEvents or its (faster) alternatives? Can't you re-design your code so that you won't have to use DoEvents, etc. anymore? As you have found out, DoEvents, et al. have re-entrancy issues which are messy to deal with. The alternative proposed by MSDN is by using the Timer control's Timer event to divide the task in chunks that can be processed intermittently.
BTW, DoEvents and its alternatives all have the same goal, and unfortunately, the same side-effects.