What does doevents do
somebody told me that it slowed down loops but i dont understand what they mean
i would assume it is to stop do loops from hoggin the computer but where should i put it and what does it accomplish in the end
Printable View
What does doevents do
somebody told me that it slowed down loops but i dont understand what they mean
i would assume it is to stop do loops from hoggin the computer but where should i put it and what does it accomplish in the end
If have a large loop it's a good idea to use DoEvents as it frees up your CPU to do run other processes that are also open.
Don't put it in every iteration of the loop. Use if x mod 100 = 0 then doevents, or something like that. with my progressbar in the form load, without doevents, it never showed the form or the progressbar. Just one doevents fixed it though.
Using it will prevent the program from hanging while your loop is running. If noting else can go on, then there isn't much point. Try it with no doevents and see if anything hangs. Add one or more to allow user intervention.
if you have a long loop, do it evertime, but i dont suggest 100, maybe 10 tops
This is a code or RobDog888....
VB Code:
Option Explicit 'Add a reference to Microsoft HTML Object Library 'Add component Microsoft Internet Controls 'Add a command button (Command1) 'Add a web browser control to the form (WebBrowser1) Dim hDoc As MSHTML.HTMLDocument Dim hCol As MSHTML.IHTMLElementCollection Dim hInp As MSHTML.HTMLInputElement Dim hSub As MSHTML.HTMLInputButtonElement Dim hTxt As MSHTML.HTMLInputTextElement Private Declare Sub Sleep Lib "kernel32.dll" (ByVal dwMilliseconds As Long) Private Sub Command1_Click() Dim iStart As Integer Dim iEnd As Integer iStart = 0 iEnd = 0 If WebBrowser1.LocationURL <> "http://www.upcdatabase.com/nocheckdigit.pl" Then WebBrowser1.Navigate2 "http://www.upcdatabase.com/nocheckdigit.pl" End If Do While WebBrowser1.Busy = True DoEvents Sleep 500 Loop Set hDoc = WebBrowser1.Document Set hInp = hDoc.getElementById("upc") hInp.focus hInp.Value = "07800008846" SendKeys "{ENTER}", True Do While WebBrowser1.Busy = True [B]DoEvents[/B] Sleep 500 Loop Set hInp = Nothing 'Parse the elements and read the values of the data returned 'Set document variable = to the new results documents page Set hDoc = WebBrowser1.Document 'Find the description: iStart = InStr(1, hDoc.body.innerHTML, "<TD>Description</TD>") + 37 iEnd = InStr(iStart, hDoc.body.innerHTML, "</TD></TR>") MsgBox Mid$(hDoc.body.innerHTML, iStart, iEnd - iStart) 'Find the Size/Weight: iStart = InStr(iStart, hDoc.body.innerHTML, "<TD>Size/Weight</TD>") + 37 iEnd = InStr(iStart, hDoc.body.innerHTML, "</TD></TR>") MsgBox Mid$(hDoc.body.innerHTML, iStart, iEnd - iStart) 'Find Manufacturer: iStart = InStr(iStart, hDoc.body.innerHTML, "<TD>Manufacturer</TD>") + 38 iEnd = InStr(iStart, hDoc.body.innerHTML, "(<A href=") MsgBox Mid$(hDoc.body.innerHTML, iStart, iEnd - iStart) 'Find the Entered/Modified: iStart = InStr(iStart, hDoc.body.innerHTML, "<TD>Entered/Modified</TD>") + 42 iEnd = InStr(iStart, hDoc.body.innerHTML, "</TD></TR>") MsgBox Mid$(hDoc.body.innerHTML, iStart, iEnd - iStart) End Sub Private Sub Form_Load() WebBrowser1.Navigate2 "http://www.upcdatabase.com/nocheckdigit.pl" End Sub Private Sub Form_Resize() If Me.WindowState <> vbMinimized Then WebBrowser1.Move 0, 0, Me.ScaleWidth, Me.ScaleHeight - 450 'Make adjustment for command button End If End Sub Private Sub WebBrowser1_NavigateComplete2(ByVal pDisp As Object, URL As Variant) ' Set hDoc = WebBrowser1.Document End Sub
Do you think the highlighted DoEvents is not necessary there?
yes, but i dont agree with the sleep 500, i dont like that at all
What do you mean by "YES"? I guess there are really situations wherein DoEvents is necessary right?
Why not check if there are any Events to "do". Call the GetQueueStatus API, if there are any events waiting to be processed call DoEvents.
VB Code:
Option Explicit 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_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 GetQueueStatus Lib "user32" (ByVal fuFlags As Long) As Long Private Sub Form_Click() Dim lngDoEventCnt As Long Dim lngLoopCount As Long Do If GetQueueStatus(QS_ALLINPUT) <> 0 Then lngDoEventCnt = lngDoEventCnt + 1 DoEvents End If lngLoopCount = lngLoopCount + 1 Loop Until lngLoopCount = 2000000 Debug.Print lngDoEventCnt End Sub
On my pc, clicking the Form and not doing anything results in 38 DoEvents being called. Much better than 200,000.
yes of course doevents is neccesary. BruceVD, thanks alot for that code-its real interesting
Hi brucevde, are those the only inputs or there are others that you didnt list?
The code covers all possible message types except for one called QS_RAWINPUT, which is only available on WinXP. Here is MSDN's explanation of raw input
Quote:
There are many user-input devices beside the traditional keyboard and mouse. For example, user input can come from a joystick, a touch screen, a microphone, or other devices that allow great flexibility in user input. These devices are collectively known as Human Input Devices (HID). The raw input API provides a stable and robust way for applications to accept raw input from any HID, including the keyboard and mouse.
In the code of RobDog888 as I have posted, I think DoEvents was needed there so it could wait for WebBrowser1_NavigateComplete2 to occur before proceeding, what kind of input is that?
They have changed the site a bit. The url to use has changed.
VB Code:
WebBrowser1.Navigate2 "http://www.upcdatabase.com/item.pl"
And the UPC's have changed also. You can use a can of coke.
VB Code:
Private Sub Form_Load() Text1.Text = "4963406" End Sub
I have just posted RobDog888's code as an example that uses DoEvents, and I wish to know what kind of input could be derived in such situations....
can you explain what you mean? doevents doesnt take any input. Here, an example will work best
VB Code:
For i = 0 to 100000 x = x + 2 next i
VB Code:
For i = 0 to 100000 x = x + 2 doevents next i
see how the first one freezing the system until its done, while the doevents ones let you continue without crashing any applicationVB Code:
For i = 0 to 100000 If (i mod 10) = 0 then doevents doevents next i
This is the input I am referring to: QS_ALLINPUT, its been used by brucevde in his code....
im still not sure of your question, but ALLINPUT refers to anything that the computer needs to process(mouse move, refresh of a picture..etc)
This ff. code is supposed to wait WebBrowser1_NavigateComplete2 before proceeding to the next lines, what kind of input is it or what kind of input will occur so doevents will be fired?
VB Code:
Do While WebBrowser1.Busy = True If GetQueueStatus(QS_ALLINPUT) <> 0 Then DoEvents End If Loop
if the mouse moves or gets clicked, something needs to be drawn on the screen, a key is pressed,a timer is fired, or a message is sent from one program to another. It will only perform a doevents when the computer has something waiting in the quene.
Hmmmmnnnn... I guess DoEvents is unnecessary in the code I cited above if I will do nothing and just wait till it finish processing? I need not click the mouse or press any keys while its doing its stuff so it means no need for DoEvents? Could it still fire WebBrowser1_NavigateComplete2 without DoEvents?
No, depending on how long it takes the page to load you need doevents. If for some reason the page didnt load, youre program would freeze and your computer would lock up. Its essential in long loops to use it, depending on your connection you should use it.
Think of it this way, your entire computer will lock up while the browser is busy.
I was thinking that DoEvents was necessary so that the CPU could also process the WebBrowser1_NavigateComplete2..... Did I think wrong?
I know the idea behind DoEvents, I just want to be clarified in the situation I'm raising....
dee-u: why are you having the wait loop there? Couldn't you have the code that is after the DoEvents loop to be in the NavigateComplete sub?
Because the processing is done asynchronously....
i concurQuote:
Originally Posted by |2eM!x
keep that there or your app will be at 100% cpu usage until the page is loaded
Hmm. I don't like the idea of DoEvents because we're operating in a preemptive multitasking operating system. I suspect that there's no way that VB can use 100% of CPU resources even though performance monitor, and task manager show this to be the case. For instance, even though 100% is shown, I have no performance problems with Word, and screen updating doesn't suffer either . . .
However, I understand the need to ensure that application appears to working cooperatively with the operating system, so I here's my idea of where to put DoEvents:
On a form with a progressbar set for 0..100
VB Code:
Option Explicit Private WithEvents mLongOperation As CLongOperation Private Sub Command1_Click() Command1.Enabled = False Set mLongOperation = New CLongOperation mLongOperation.DoSomething Set mLongOperation = Nothing Command1.Enabled = True End Sub Private Sub mLongOperation_ProgressNotification(ByVal Value As Long) ProgressBar1.Value = Value DoEvents End Sub
. . .and the class declared on the form:
VB Code:
Option Explicit Public Event ProgressNotification(ByVal Value As Long) Private Sub Class_Initialize() ' End Sub Private Sub Class_Terminate() ' End Sub Public Function DoSomething() On Error GoTo ERR_DoSomething Dim i As Long Dim MaxValue As Long MaxValue = 100000000 For i = 0 To MaxValue If i Mod 1000 = 0 Then RaiseEvent ProgressNotification((i / MaxValue) * 100) End If Next Exit Function ERR_DoSomething: Err.Raise Err.Number, Err.Source, Err.Description, Err.HelpFile, Err.HelpContext End Function
If I were doing this across the network I would use a COM Callback. ie I only use VB events for local stuff. I use the COM marshaller for everything else.
A program of mine used this and the CPU Usage was very high....Quote:
Originally Posted by VaxoP
VB Code:
Do While WebBrowser1.Busy = True If GetQueueStatus(QS_ALLINPUT) <> 0 Then DoEvents End If Loop
But when I inserted an Sleep in it the CPU Usage went down very low!
VB Code:
Do While WebBrowser1.Busy = True Sleep 1 If GetQueueStatus(QS_ALLINPUT) <> 0 Then DoEvents End If Loop
Could anybody tell me what happen? It seems its the opposite of what VaxoP said!
Originally Posted by |2eM!xQuote:
Originally Posted by dee-u
yes, but i dont agree with the sleep 500, i dont like that at all
i concur
keep that there or your app will be at 100% cpu usage until the page is loaded
-------------------
i mean, keep the sleep statement there or you will have 100% cpu usage
That's what I quoted and in my case it was exactly the opposite that I achieved, with the Sleep in there the CPU Usage actually went down....
is that because it freezes your computer? maybe it makes everything stop working, thus the lower percentage
I think it was really CPU intensive, refreshing a page constantly but when I inserted Sleep 1 in it the CPU Usage went really low and the app still works as expected... Why is that?
im not sure anymore..i honestly have no clue...I guess we will have to wait for one of the elite members here to help with this one
The worst thng about DoEvents is it can screw with your code execution. If you have events firing that depend on data handled by other events, placing a Doevents in one event can cause the other event to start executing. This sort of thing really messes up program flow.
This is because DoEvents allows *all* other code that is waiting to be exeucted, to run. Sleep on the other hand doesn't allow any code from your process to run, it merely pauses the process for the specified time and this allows other process to get the CPU control.
In a loop, Sleep is the best thing to allow other processes to run, however if you have things waiting in your own process then DoEvents is really the only way to go. (there are other APIs you can use but I've forgotten them :() Brucevde's code looks like a really way of using it :thumb:
As Per Penagate's statement, it seems my code below is valid?
VB Code:
Do While WebBrowser1.Busy = True Sleep 1 If GetQueueStatus(QS_ALLINPUT) <> 0 Then DoEvents End If Loop
Yes. You can further speed that up by trimming the fat from your If block a bit.
I believe that compiles to smaller code, unless the VB optimiser is more advanced than I thought.VB Code:
Do While WebBrowser1.Busy = True Sleep 1 If (GetQueueStatus(QS_ALLINPUT)) Then _ DoEvents Loop
I didn't think that the WebBrowser could lock up your program, if a DoEvents wasn't used. Shouldn't it automatically have a type of DoEvents? Or be its own thread or whatever?
chem
No it doesn't lock it up it's just that dee-u is using a loop and repeatedly checking the .Busy property.
DoEvents will yield the execution of the current running code and give the application time to process other events that might be queued such as repainting the window and process keyboard and mouse events.
In the code posted by Dee-u above there is a loop that allows the webbrowser control to finish loading the page before it continues. Calling DoEvents here would be necassary for the window to refresh itself. The user could for example have switch to another window and then switched back to this form. The user would then expect that the window to be redrawn. Or he might hit the maximize button and of course then expect it to maximize, none of which it would do until the sub has finished unless there was a DoEvents call.
The reason RobDog added a Sleep call is simply to let the application wait half a second before it continues the loop. If it would have looked like this:DoEvents would probably have been called a million times if it takes a while for the webbrowser to load the page, calling it that many times would be a complete waste of time. This code:VB Code:
Do While WebBrowser1.Busy DoEvents Loopwouldn't call DoEvents more then necassary but on the other hand it would call the GetQueueStatus API function a million times instead, which is also a complete waste of CPU cycles. The user wouldn't probably care if the code takes one half of a second extra to complete after the page is loaded (in real life it would be more like 250 ms extra).VB Code:
Do While WebBrowser1.Busy If GetQueueStatus(QS_ALLINPUT) DoEvents End If Loop
Merri suggested that the code after the loop should be moved to the NavigateComplete event instead and therefor the loop would be unnecassary in the first place, and that is correct. However doing the HTML parsing in that event suggests that you always want to parse the HTML document after you have navigated to a particular URL, which might not be the case so I think the code is just fine as it looks. Of course if you really want to use the GetQueueStatus API the code should probably look something like this:I'm not saying that sleeping for 500 ms is the ideal time, you could change that to 100 or 200 or whatever you find would be appropriate but sleeping here and then process mouse, keyboard, and paint events is a good practice for that example.VB Code:
Do While WebBrowser1.Busy If GetQueueStatus(QS_ALLINPUT) DoEvents End If Sleep 500 Loop
I cant believe I read a whole thread on DoEvents. :D
Interesting to see all the points of view on my loop. I sure am glad I got the loop correct or you all would have been
bashing me for 40+ posts :lol:
i was just about to get to that : )
Well, this is post number 41 in this thread so if I give you a little bashing here you would at least got bashed in post 40+ LOLQuote:
Originally Posted by RobDog888
Bad code, Rob, bad bad bad bad bad :)
Ah, thats more like it. :lol:
GetQueueStatus looks interesting. I'll have to check it out.
Congrats on 6K+ posts JA. :thumb:
congrats on 13,893 posts RD
In such example, if you set the Sleep to 500, does it mean there is a wasted 250 ms since it only takes about 250 ms to accomplish the loading?Quote:
Originally Posted by Joacim Andersson
It can take several seconds for a webpage to be loaded into the webbrowser object. The loop in this case checks if it's done loading every half second, so let's say that you check if it's finished, and it's not so you wait 500ms, but already 1ms after that the load was done in which case you've "wasted" 499 ms. What I meant is that on average the extra time you wait after the webbrowser is done loading would be 250ms.Quote:
Originally Posted by dee-u
HOWTO: Determine the Differences Between DoEvents and Sleep
Q158175
SUMMARY
This article explains the differences between the Visual Basic DoEvents function and
the Sleep() Windows API function.
MORE INFORMATION
DoEvents is a Visual Basic function that yields execution so the operating system can
process other events. This function cleans out the message loop and executes any other
pending business in the Visual Basic runtime. Upon completing the pending business
execution, the function calls the Sleep function with zero (0) as the argument so that
the remaining time slice can be used to check the queue.
The Sleep 32-bit API function is a subset of the DoEvents function. The Visual Basic
program calling the function and the Visual Basic runtime executable and interactions
with Windows are immediately put to sleep by this function. The programs remain inactive
for the time in milliseconds specified in the Sleep argument.
The Sleep function allows you to specify the amount of time your applications are
inactive. The DoEvents function returns control to the Visual Basic program after
the operating system has finished processing the events in its queue and all keys in
the SendKeys queue have been sent.
The information in this article applies to:
Microsoft Visual Basic Learning Edition for Windows 5.0
Microsoft Visual Basic Learning Edition for Windows 6.0
Microsoft Visual Basic Professional Edition for Windows 5.0
Microsoft Visual Basic Professional Edition for Windows 6.0
Microsoft Visual Basic Enterprise Edition for Windows 5.0
Microsoft Visual Basic Enterprise Edition for Windows 6.0
Microsoft Visual Basic Standard Edition, 32-bit, for Windows 4.0
Microsoft Visual Basic Professional Edition, 32-bit, for Windows 4.0
Microsoft Visual Basic Enterprise Edition, 32-bit, for Windows 4.0
Last Reviewed: 5/13/2003 (3.0)
Keywords: kbhowto KB158175
Yes, I agree; I think that DoEvents can be very dangerous. If, for instance, you have a COM Server (of which only 8, by default, instances are allowed) and you put a DoEvents in one of the function calls then you will have a nasty case of corrupt synchronisation, and get reentrancy problems.Quote:
Originally Posted by penagate
DoEvents should always be used with care, and never in any form of shared code.
The best thing to do when it comes to webbrowser is to avoid the do while and instead move your code to the documentcomplete event and maybe sort your code based on where the browser is one example is
in documentcomplete event
select case Webbrowser1.document.title
case "google"
'Do some search stuff with google
case "UPC database"
'Enter a upc
end select
using this way will completely free up the application until page is loaded
and also you can trap 404 pages and other error pages by title