You don't need to place em in every for next loop. DoEvents does tend to slow the program down a notch if used in multiple places. The only time its really needed in a For...Next loop is when you loading 100s-1000s of things and should be placed at the end of your loop. If in a Do Loop however, you need it at the end of the loop as well.
inside a loop is fine. Putting it anywhere in the loop is generally fine. Typically, it's done at the end of the loop. What I wouldn't recommend is having the DoEvents execute EVERY iteration of the loop. I'd add a counter, and then check it's value and execute the DoEvents, maybe once every 10 or so loops...
inside a loop is fine. Putting it anywhere in the loop is generally fine. Typically, it's done at the end of the loop. What I wouldn't recommend is having the DoEvents execute EVERY iteration of the loop. I'd add a counter, and then check it's value and execute the DoEvents, maybe once every 10 or so loops...
-tg
I have heard that suggestion before and have always wondered if there is a bigger hit calling DoEvents or checking a counter to see if you should call DoEvents.
In my opinion, you can use DoEvents() in the loop (normally is While loop), and of course you can use anywhere in your project (as LaVolpe said). Have fun!
Opinion about Doevents ? OMFG its unbelievably effin dangerous. I get nightmares about it......I wrote one application in the past where I could not avoid using it and goddamn!!! ENDLESS HEADACHES. Was nothing short of a miracle I got that app to work at all.
IF YOU CAN AVOID IT DO NOT USE IT. I SAY TO YOU DONT USE IT IF YOU CAN AVOID IT
Quite a few years ago I was doing some experimenting with different methods other than DoEvents and found DoEvents to be the slowest. TranslateMessage and DispatchMessage, although not shown in the DoEvents_Fast() sub even though its another alternative, is commonly used in C++. Note that this code was from many many years ago.
vb Code:
Option Explicit
Public 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
Public Declare Function GetInputState Lib "user32" () As Long
Public Declare Function GetQueueStatus Lib "user32" (ByVal qsFlags As Long) As Long
Public Declare Function GetMessage Lib "user32" Alias "GetMessageA" (lpMsg As MSG, ByVal hwnd As Long, ByVal wMsgFilterMin As Long, ByVal wMsgFilterMax As Long) As Long
Public Declare Function TranslateMessage Lib "user32" (lpMsg As MSG) As Long
Public Declare Function DispatchMessage Lib "user32" Alias "DispatchMessageA" (lpMsg As MSG) As Long
Public Const WM_SYSCOMMAND As Long = &H112
Public Const WM_CLOSE As Long = &H10
Public Const WM_DESTROY As Long = &H2
Public Const PM_NOREMOVE As Long = &H0
Public Const QS_HOTKEY = &H80
Public Const QS_KEY = &H1
Public Const QS_MOUSEBUTTON = &H4
Public Const QS_MOUSEMOVE = &H2
Public Const QS_PAINT = &H20
Public Const QS_POSTMESSAGE = &H8
Public Const QS_SENDMESSAGE = &H40
Public Const QS_TIMER = &H10
Public 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)
Public Const QS_MOUSE = (QS_MOUSEMOVE Or QS_MOUSEBUTTON)
Public Const QS_INPUT = (QS_MOUSE Or QS_KEY)
Public Const QS_ALLEVENTS = (QS_INPUT Or QS_POSTMESSAGE Or QS_TIMER Or QS_PAINT Or QS_HOTKEY)
Public Sub DoEvents_Fast()
'This does events only when absolutely necessary and still prevents
'your program from locking up. The result is a Do loop that is
'multiple times faster than an ordinary Do/DoEvents/Loop, which is needed for
'realtime loops. I've experimented with multiple methods I've found on Planet
'Source Code, and here are my results:
'Note - This all has been done on my AMD Athlon 1.2 Ghz Processor. Results may vary.
Heheh. Niya, I feel your pain. But I think it is the only solution in many instances. Odd thing was, until just recently, I never really had any issues with it. And I've been using vb since 1998! But this week it took me about a day and a half to figure out that DoEvents was my enemy. Er...rather, my usage of DoEvents was my enemy!
What I had was a situation where procedures were calling procedures were calling procedures, and in those those procedures were a bunch of loops that went round and round, some processing maybe a 1000 cycles. So if I didn't put a DoEvents inside the really long-winded loops, I had no way to get control back until they were finished. To make a long story short, whenever I would click a Pause/Continue toggle button to stop them in they're tracks, it took all control to an idle procedure which was an infinite Goto loop with another DoEvents inside it. If I just re-clicked Pause/Continue, everything would be fine. But if I clicked the Proceed button (which essentially starts everything from scratch, THAT's when the world came apart at the seams. The program would function fine, seem to finish, and then go haywire, going to seemingly random spots in the code. But in sorting it all out, it wasn't random at all. I realized that even though I essentially restarted, I still had a bunch of calls from the old aborted attempt, just garbage now sitting in the stack. It was simply processing the garbage calls. And those caused really odd behavior in the loops...Like ignoring the For statement's right "bounds" and using the one from the garbage information, whatever that might be!
So the solution was to have a flag at the top of the Proceed_click procedure that was set if I hit the Proceed button while still in Pause mode, and before actually processing the new Proceed click, would unwind all of those garbage calls by telling each returned-to procedure to exit immediately to ITS calling procedure...all the way back to the Proceed procedure. THEN the actual Proceed process would start again. The idle procedure looked like this:
Code:
Private Sub Pause_Continue_cmd_Click()
'PauseFlag = 1, Continue
'PuaseFlag = -1, Pause
PauseFlag = -PauseFlag
If PauseFlag = 1 Then
Pause_Continue_cmd.Caption = "Pause"
Pause_Continue_cmd.BackColor = &HFFFFC0 'Light-Blue
Else
Pause_Continue_cmd.Caption = "Continue"
Pause_Continue_cmd.BackColor = &H8080FF 'Mid-Red
End If
EndlessLoop:
DoEvents
'THIS DECISION BLOCK IMMEDIATELY NEEDS TO FOLLOW ALL DoEvents LINES, AND
'AFTER ANY CALL STATEMENTS THAT JUMP TO PROCEDURES THAT CONTAIN DoEvents LINES:
If ReProceedFlag = 1 Then 'The "Proceed" button was clicked while in Pause mode.
Exit Sub
End If
If PauseFlag = 1 Then Exit Sub
GoTo EndlessLoop
End Sub
And at the very top of my Proceed_click procedure was :
Code:
ReProceed:
If PauseFlag = -1 Then 'Presently still in Pause mode.
ReProceedFlag = 1
PauseFlag = 1
Pause_Continue_cmd.Caption = "Pause"
Pause_Continue_cmd.BackColor = &HFFFFC0 'Light-Blue
Exit Sub
End If
And just after that very first call in Proceed_click, was a special form of the If/Else block:
Code:
'THIS DECISION BLOCK IMMEDIATELY NEEDS TO FOLLOW ALL DoEvents LINES, AND
'AFTER ANY CALL STATEMENTS THAT JUMP TO PROCEDURES THAT CONTAIN DoEvents LINES:
'This particular block needs to be different because it occurs in the topmost calling procedure:
If ReProceedFlag = 1 Then 'The "Proceed" button was clicked while in Pause mode.
' Exit Sub
ReProceedFlag = 0
GoTo ReProceed
End If
Not that that is elegant, necessarily, but it DID do the trick. But it means putting that little IF/Else block after every DoEvents line and all calls to procedures with DoEvents in them.
Anyway...Loads of fun, not. So I learned a valuable lesson. Don't be lazy...Always include code to empty the stack of garbage, because there is no way in vb6 (except maybe via the API??) to empty out the stack with one statement.
-------------------
Jacob Roman, you JUST posted before I could get my post up. Do you have an idea how much faster the API method is. I've seen dramatic speed increases with the API, and this would certainly help in my situation.
Last edited by treddie; Jan 23rd, 2012 at 01:51 AM.
I always use Doevents with DO & WHILE loops to prevent accidental infinite looping
But can't a Do loop fail the Until/While part just like a For loop fails the Next part? If any loop is re-entered with garbage data in the stack, wouldn't the effect be the same?
Jacob Roman > Please disregard my performance question, when I scrolled down through your code, I saw your performance figures. 14% faster is fairly substantial.
If I "mess up" the code in a way that for some reason I think there might not be exit from the loop or the code inside the loops ends up "bloating",
DoEvents will only allow you to terminate the app with task manager for example.
At least this is how/why I use doevents most of the times.
But Im not even near close being a good programmer, so I'm just sayin'
Here is a contrived demo showing what Microsoft suggests for managing long-running loops in the VB6 manuals.
With the tuning parameter values in the code now, this is best tested after compiling to native code. If you want to compare in the IDE you will probably want to lower the "big loop" limit and tweak the parameters a bit.
I don't expect anyone to listen though, which is just fine. Doing things correctly is what we call competitive advantage out here where we code for money.
And if ayone has a more reliable, general solution I'd love to hear it. Especially something that works when you have an external event source you need to service such as a Winsock control, an MSComm control, MSMQ objects, SysInfo control, MCI control, async ADO Connection objects, HTTP Request objects, Inet controls, etc.
I have heard that suggestion before and have always wondered if there is a bigger hit calling DoEvents or checking a counter to see if you should call DoEvents.
That statement right there is what is wrong with people using DoEvents... a simple lack of fully understanding what it does and why it can be detrimental. The short answer to your question is that the counter check is less of a performance hit. And here's why:
When you call DoEvents, you actually momentarily SUSPEND your thread (perf hit #1) so that the system can check (perf hit #2) to see if there are any other pending messages in the queue, and if so allow them to be processed (perf hit #3 and so on)... A common reason people use DoEvents is to allow their screen to remain responsive while stuck in a loop doing something. Which is fine... in VB6 it's the only way... well at the least it's the most commonly used way, you can subclass in VB6, but it's a bit more work. At any rate, my point is that doing a simple compare (if then) is less intrusive than automatically calling DoEvents each time. The trick is finding out the right number to count to before calling it. I try to divide my loops in to equal segments, depending on the size. If I don't know the size, I usually start with a factor of 10.
I have heard that suggestion before and have always wondered if there is a bigger hit calling DoEvents or checking a counter to see if you should call DoEvents.
Checking involves a relatively simple If statement, which is almost the fastest code there is... DoEvents does so many different (and "unpredictable") things that is near the other end of the scale.
Originally Posted by treddie
Jacob Roman, you JUST posted before I could get my post up. Do you have an idea how much faster the API method is.
Jacob Roman > Please disregard my performance question, when I scrolled down through your code, I saw your performance figures. 14% faster is fairly substantial.
In my experience the difference is usually less than 1%, so I guess that as with many things the speed varies based on the circumstances.
Originally Posted by techgnome
At any rate, my point is that doing a simple compare (if then) is less intrusive than automatically calling DoEvents each time. The trick is finding out the right number to count to before calling it. I try to divide my loops in to equal segments, depending on the size. If I don't know the size, I usually start with a factor of 10.
There's no need to work out a factor (which varies when compiled, or when you add/alter code, etc), just do it based on something time instead, eg:
Code:
Public Sub DoEventsIfApt
Static NextTime as Single
Dim CurrentTime as Single
CurrentTime = Timer
If (CurrentTime < NextTime) Then
If Not (CurrentTime + 10 > NextTime) Then 'deal with Timer 'wrapping' at midnight
Exit Sub
End If
End If
DoEvents
NextTime = Timer + 0.2 'the number of seconds gap (don't normally need to change it)
End Sub
This is untested, but is very similar to what I normally use with DoEvents.
Having said all of that however, dilettante's post contains a very good alternative for many situations.
Honestly, I never thought about making it time-based. That's certainly something I'll have to remember. The last time I needed to use it was in processing some data that was coming back from a web service in chunks, and we knew the size of the chunks (500 records at a time), so it was easy to put a .count mod 50 = 0 check and run DoEvents which then resulted in acceptable performance for hte data and responsiveness of the UI (the users wanted to see their data loading in chunks, and yet a progress bar or wait symbol was out of the question)
Given that the connection could be via LAN, WAN, or even SatLAN, a time-based interval may not have worked in that case.
The time-based method I showed isn't a perfect solution, but it limits the minimum frequency that DoEvents can run (in my example, at least 0.2s after the previous).
If the gap is larger (due to network delays etc), it will run immediately. Admittedly that could mean that just the first record shows to start with, then the next 51 or whatever... in cases like that I generally set NextTime just before the loop.
Using those two variations of the idea, I have yet to find a situation where it isn't at least equal to the Mod idea - and it takes no effort to work out (or guess) the frequency you want.
I agree you can write the logic to "self tune" for a good balance between responsiveness and workload completion rate either using the "occasional DoEvents" or a Timer approach. You still end up with a few constants to jigger but at least once you have those set the code will accommodate itself to variations in CPU speeds, environment, and overall system workload or other limiting factors.
And there are a few safe ways to have a background worker thread or separate process.
And there are a few safe ways to have a background worker thread or separate process.
Are you referring to vb.net and multi-threading, or actually running an external process that the <= vb6 program communicates with? Or something else, maybe?
There are ways to use an ActiveX EXE to host additional threads via the Thread Per Object setting, though it gets complicated. There are a few 3rd party libraries that provide a way to allocate and run worker threads in a VB6 program as well. Most of these are complicated and unsatisfactory enough to make them rarely used though.
Yes, you can create a Form-less VB6 program to act as a worker process. You can either start it using the Shell() command and use variations on shell-and-wait to detect when it has completed (polling using a Timer works best). You can also use CreateProcess to run it, and this allows StdIO redirection through anonymous pipes so your main program has a way to "talk to it" instead of using something like disk files to pass data into it and back from it. Or you might use something hackish like Winsock controls, or clean and fast like Named Pipes to talk between them.
None of this is easy enough to be valuable for general use though. You only go to the effort in specialized cases that leave you little choice.
Most of those options don't give you "workers" that can see the global data in the "main" thread, which is why you have to ship data around. Even if they did, you'd now have to deal with locks and synchronization so they didn't step on each other.
It would be absolutely necessary in vb6 for programs that really DO need a speed increase from multi-threading. I had a program once that calculated the position and velocity of a spacecraft on its way from someplace in the Solar System to any other place in it. Where the parallel-ness (new word? ) was needed was calculating each planet's position and velocity at each time step, so that all of that info could be brought together to calculate the spacecraft's state vector. Otherwise, it was too damn slow. I had to port it over to .net to do that, because I never thought of trying to get multithreads into vb6. And I REALLY like vb6 a ton better than .net. Especially with the "easy" access vb6 has to the API. I would be much faster at the API approach if I had the opportunity to use it more often.
I think any time that a finite element method is required, multi-threading in vb6 would be a must.
When using the: "DoEvents" command, use it sparingly. You only have to use it, when you are running many processes together that are running alongside eachother. Like a very long winded Timer handler, or even something else like a Winsock Connection, as such...
I have a huge free products range, of computer software in which you can download using any kind of 64-Bit Web Browser. Also there is coming a Social Networking section that I am making on my Website...
|Ambra Productions Inc. | The Black Sun Society | The Black Shield | Ambra College | Church of the Black Sun | Ambra Productions Inc's Homepage | Boomtick Venues: Ambar Nightclub, Jack Rabbit Slim's, Villa Nightclub and Lucy's Love Shack | Pasta Ambra | Fish Feast Company | Wallet Wizard | Ambrose Liquor | Ambar Tavern | Ambra University | Ambra Cheese |
Do you wish to do unpaid work for me??? If so, the PM me on this Forum, and then we can get to work, programming for the future of computers go by the name of ThEiMp. This is my ghost writers name. Also my nickname, means that I am: The Imperial of the Technology Industry, so then to make it really short, I just then wrote: The Imp, which is where I get the nickname from...
Question: So you're trying to multi processor support a VB6 app, right???
I have a huge free products range, of computer software in which you can download using any kind of 64-Bit Web Browser. Also there is coming a Social Networking section that I am making on my Website...
|Ambra Productions Inc. | The Black Sun Society | The Black Shield | Ambra College | Church of the Black Sun | Ambra Productions Inc's Homepage | Boomtick Venues: Ambar Nightclub, Jack Rabbit Slim's, Villa Nightclub and Lucy's Love Shack | Pasta Ambra | Fish Feast Company | Wallet Wizard | Ambrose Liquor | Ambar Tavern | Ambra University | Ambra Cheese |
Do you wish to do unpaid work for me??? If so, the PM me on this Forum, and then we can get to work, programming for the future of computers go by the name of ThEiMp. This is my ghost writers name. Also my nickname, means that I am: The Imperial of the Technology Industry, so then to make it really short, I just then wrote: The Imp, which is where I get the nickname from...
Well, actually the multiproc thing developed out of this thread as an expansion of what I originally posted. I will stick with DoEvents on this project, but I am VERY interested in using multiprocessing in vb6 for programs that use the Finite Element Method, or any numerical problem that can be broken up into parallel tasks.
-- Try Apartment Threading, which is in the Project Properties DialogBox, on the VB6 MenuBar???
Ps: Apartment Threading = Some sort of Hardware/Software Multiprocessor Processes. (Processor must be Multi Core or even Muti Processor, to support this. If not, then cannot run the Project!! Danger Will Robertson, Danger...
I have a huge free products range, of computer software in which you can download using any kind of 64-Bit Web Browser. Also there is coming a Social Networking section that I am making on my Website...
|Ambra Productions Inc. | The Black Sun Society | The Black Shield | Ambra College | Church of the Black Sun | Ambra Productions Inc's Homepage | Boomtick Venues: Ambar Nightclub, Jack Rabbit Slim's, Villa Nightclub and Lucy's Love Shack | Pasta Ambra | Fish Feast Company | Wallet Wizard | Ambrose Liquor | Ambar Tavern | Ambra University | Ambra Cheese |
Do you wish to do unpaid work for me??? If so, the PM me on this Forum, and then we can get to work, programming for the future of computers go by the name of ThEiMp. This is my ghost writers name. Also my nickname, means that I am: The Imperial of the Technology Industry, so then to make it really short, I just then wrote: The Imp, which is where I get the nickname from...
Do you have Dual/Tri/Quad Core Pentium IV??? Or even an: i3/i5/i7 type Processor??? You must have one of those, to do that. Like I said, in my last post. You have to read the whole post, because there is a lot of information in them!!
I have a huge free products range, of computer software in which you can download using any kind of 64-Bit Web Browser. Also there is coming a Social Networking section that I am making on my Website...
|Ambra Productions Inc. | The Black Sun Society | The Black Shield | Ambra College | Church of the Black Sun | Ambra Productions Inc's Homepage | Boomtick Venues: Ambar Nightclub, Jack Rabbit Slim's, Villa Nightclub and Lucy's Love Shack | Pasta Ambra | Fish Feast Company | Wallet Wizard | Ambrose Liquor | Ambar Tavern | Ambra University | Ambra Cheese |
Do you wish to do unpaid work for me??? If so, the PM me on this Forum, and then we can get to work, programming for the future of computers go by the name of ThEiMp. This is my ghost writers name. Also my nickname, means that I am: The Imperial of the Technology Industry, so then to make it really short, I just then wrote: The Imp, which is where I get the nickname from...
If I'm understanding my quick scan of the article, it looks like a lot of the debugging has to be via an external debugger, which I assume means memory and register dumps and such. If so, that reminds me of my old assembly days!
This is what all VB6 programs use. It has nothing to do with hardware, being a software concept native to COM.
-- Really, I thought that was some sort of hardware config. However I did know that COM supported it, as software too!!
!! Thanks for the Input$ !!
I have a huge free products range, of computer software in which you can download using any kind of 64-Bit Web Browser. Also there is coming a Social Networking section that I am making on my Website...
|Ambra Productions Inc. | The Black Sun Society | The Black Shield | Ambra College | Church of the Black Sun | Ambra Productions Inc's Homepage | Boomtick Venues: Ambar Nightclub, Jack Rabbit Slim's, Villa Nightclub and Lucy's Love Shack | Pasta Ambra | Fish Feast Company | Wallet Wizard | Ambrose Liquor | Ambar Tavern | Ambra University | Ambra Cheese |
Do you wish to do unpaid work for me??? If so, the PM me on this Forum, and then we can get to work, programming for the future of computers go by the name of ThEiMp. This is my ghost writers name. Also my nickname, means that I am: The Imperial of the Technology Industry, so then to make it really short, I just then wrote: The Imp, which is where I get the nickname from...
If you are using Visual Basic 6, in the COM section. Then I suggest Application Preformance Manager, for the Enterprise Edition...
I have a huge free products range, of computer software in which you can download using any kind of 64-Bit Web Browser. Also there is coming a Social Networking section that I am making on my Website...
|Ambra Productions Inc. | The Black Sun Society | The Black Shield | Ambra College | Church of the Black Sun | Ambra Productions Inc's Homepage | Boomtick Venues: Ambar Nightclub, Jack Rabbit Slim's, Villa Nightclub and Lucy's Love Shack | Pasta Ambra | Fish Feast Company | Wallet Wizard | Ambrose Liquor | Ambar Tavern | Ambra University | Ambra Cheese |
Do you wish to do unpaid work for me??? If so, the PM me on this Forum, and then we can get to work, programming for the future of computers go by the name of ThEiMp. This is my ghost writers name. Also my nickname, means that I am: The Imperial of the Technology Industry, so then to make it really short, I just then wrote: The Imp, which is where I get the nickname from...
You can probably debug the bulk of your logic without using multithreading. Just add that after the application logic has been stabilized. Then you can debug the threading and concurrency issues.
Most people prefer to use an approach based on threading in a secondary ActiveX EXE though. No 3rd party library required then, but you still have the debugging issues.
There are other techniques that delegate "background" operations to a second Form-less standard EXE. Usually you need some form of IPC to pass data back and forth as well as to signal completion. There are plenty of IPC choices available. This avoids the need for any 3rd party libraries and avoids ActiveX EXE registration requirements - normally only a big issue for portable applications (applications with no formal installer).
Please remember that the term: Debugging, doesn't mean the command process: Debug.Print, so forget that in this process...
Also please note: That I haven't slept for about thirty seven hours, then my spelling it getting a little off. So please correct me, I have been editing this thread post, of mine for a long time!!
I have a huge free products range, of computer software in which you can download using any kind of 64-Bit Web Browser. Also there is coming a Social Networking section that I am making on my Website...
|Ambra Productions Inc. | The Black Sun Society | The Black Shield | Ambra College | Church of the Black Sun | Ambra Productions Inc's Homepage | Boomtick Venues: Ambar Nightclub, Jack Rabbit Slim's, Villa Nightclub and Lucy's Love Shack | Pasta Ambra | Fish Feast Company | Wallet Wizard | Ambrose Liquor | Ambar Tavern | Ambra University | Ambra Cheese |
Do you wish to do unpaid work for me??? If so, the PM me on this Forum, and then we can get to work, programming for the future of computers go by the name of ThEiMp. This is my ghost writers name. Also my nickname, means that I am: The Imperial of the Technology Industry, so then to make it really short, I just then wrote: The Imp, which is where I get the nickname from...