Simple Loop Break..even simpler dummy!

Wuff

New member
Local time
Today, 14:17
Joined
Sep 17, 2002
Messages
8
Ya know, sometimes things just don't click ? I missed a major turn on this one. I don't have a clue how "DoEvents" is used, even tho I have read till I am blue in the face ! It just does not turn the little light on for me. Duh !

I understand it turns loose, so I can click on the form and I am using a timer around it.


I am running a loop 24/7 and need to be able to stop it if we are not using the program. I start it with a form check box and when I try to use same box or another box to stop it... it hollers about my macro or function being updated or trying to save...

I just don't understand what goes along with the "DoEvents" line. What other lines are associated with the "DoEvents"? Can anyone explain the "DoEvents" differently that all the help comments? Guess I need it in dummy words, even tho I do have a fairly good understanding of vb an access.

I call the loop from the check box, which calls a macro to call a function that runs the loop. Sheesh, I am getting so goofy on this that I am not making much sense ! LOL

-----------------------------------------------------------
Private Sub AutoON_Click()
Dim PauseTime, Start, Finish, TotalTime
Dim aon As Integer
aon = Forms!AutoA!AutoON
Do While aon = -1
PauseTime = 5
Start = Timer
aon = Forms!AutoA!AutoON
Do While Timer < Start + PauseTime
DoEvents
Loop
Finish = Timer
TotalTime = Finish - Start
'24/7 program runs here <------- will actually run every 25minutes.
aon = Forms!AutoA!AutoON
Forms!AutoA!AutoON.SetFocus
Loop
End Sub
-----------------------------------------------
This runs fine, until I hit the button again. Then I get the following message.

"The macro or function set to the BeforeUpdate or ValidateRule property for this field is preventing MicroSoft from saving the data in the field."
:confused: :confused: :confused:
 
Last edited:
These kind of loops are bad practice in Access usually. I would convert it to use a form timer instead. Just have you button enable or disable the timer.
 
To answer the question more directly (though I STRONGLY agree with FoFa about putting this as a Form Timer function),...

DoEvents is most importantly used when you have something running in the foreground. I.e. a maximized window that is currently "on top." Depending on the version of Windows (NT family is different from traditional family in this case), foreground processes can hog your CPU resource completely. If pending events aren't part of a higher priority task, DoEvents tells Windows to do whatever it has been holding back while waiting for your foreground process to relinquish the CPU.

In background tasks with minimized windows and such, DoEvents still allows lower-priority background tasks their shot at the CPU. So basically, you would use DoEvents as a fairness issue.

Now, ONE thing that is REALLY important if you are debugging is that you'll get better response to the BREAK function key if the loop that is locked up happens to include a DoEvents call.
 
Guys, I appreciate your responses !!;)
However, this program is not important. What I need to know is, what lines need to be inserted to provide a stop signal. I don't understand where the reaction to the DoEvents is written, nor what is needed to take advantage of the DoEvents. As I have tried to state, I am missing a simple understanding of how to take advantage of clicking a button to stop a loop, using the DoEvents. What lines are needed in the loop program and what is needed to be placed in the "On click " of the button or buttons ?

Note: I am not going to use this as a de-bugging effort. I have a program that will be placed on its' own computer and will run 24/7. If for some reason, the program needed to be halted, I want to let it finish it's current work and close at the proper end of a cycle. I just want a stop button on the control panel button, so that simple folks could turn off the program if they wanted to.
 
Last edited:
to stop all vb code from running try Ctrl+Break/Pause
 
Chewy, I don't want to break the running program in the middle of something. It must finish it's cycle before quitting.
 
I think you misunderstand Doevents. Doevents is designed to return prioity to the OS to run other tasks. It is like a break in your program to let the OS do it's thing. From the code you pasted, it would appear it is not detecting the resetting of your AON variable. I assume you are trying to uncheck the control, detect this in your loop and quit. While there looks like nothing wrong with this, these kind of loops in Access never seem to act the way you think. Main reason I use a timer control instead.
 
FoFa.... You are dam straight I don't understand DoEvents !!
Ok... how can I use a timer that does not stop the loop until I tell it to stop ? I may want this loop to run for years without a break.

Maybe I can call you or someone and talk to them.. I am not making much progress this way.
 
Last edited:
basically a timer control is wait this long, than do this. If wait this long (interval property I think) is = zero, it is disabled, anything else, it waits that length of time (in milliseconds I believe) and then runs what you tell it to. So your button would set the interval on the timer control to zero (off) or what ever interval you desire (on). And you tell it to run your code on the timer event. I have not used one in a couple years, but it is pretty basic. And while it is waiting, the system is free to do what ever it wants.
 
Suddenly the light went on in MY head.

The reason you are having trouble is precisely because you are NOT running this loop where it should be run. An event cannot interrupt another event on the same form unless there is a DoEvents call in the active event's code.

I.e. If you have a loop in a Form_Current routine AND a timer set so that you have a Form_Timer routine that COULD be active, the timer WON'T be active unless you let in other events with DoEvents from the Form_Current loop. I forgot for a moment that the scheduler rule is that an event cannot interrupt another event in the same task. Events are queued into an event process queue. Events occur when they occur but they are processed linearly. Which is why you can do typeahead and still have key-up or key-down events work right. They are just held until they are used.

Here is how I would approach the problem. You say you want to be able to press/click a button to do something. Buttons imply that forms are present, so I can assume form-event based code.

1. In the form's Class Module declaration area: Define a boolean state variable to show whether the button has recently been clicked. Whatever way it is loaded, it should always start life as a FALSE vlog.

2. In the Form_Load or Form_Current routine, set up a timer for the loop using a number of milliseconds in the Form.TimerInterval. Assure that the state variable is FALSE.

3. In the Form_Timer, test the boolean variable. If it is still FALSE then reload the Form.TimerInterval. If it is true, do nothing.

4. Once the timer is running, you can minimize the form if you like. The timer will run anyway.

When you click the button, you set the flag. When the timer event tests the flag and it is found to be SET, you can do nothing. Reset the Form.TimerInterval to 0. At this point your timer is quiescent.
 
Doc !! I think you have it figured out ! I tried running the vb module on it's own and then asked the form to stop it... It worked! Aparently your correct in thinking the two form buttons were fighting each other.

Now, as I have printed your comments and studied them since you sent it, I am still lost as to how I accomplish some of the things you suggest.

1. In the form's Class Module declaration area: Define a boolean state variable to show whether the button has recently been clicked. Whatever way it is loaded, it should always start life as a FALSE vlog. .I have no idea where to find this, nor what to do with it.

2. In the Form_Load or Form_Current routine, set up a timer for the loop using a number of milliseconds in the Form.TimerInterval. Assure that the state variable is FALSE. .I found the Timer/Interval location, but the "state variable" part lost me.

3. In the Form_Timer, test the boolean variable. If it is still FALSE then reload the Form.TimerInterval. If it is true, do nothing. .I know how to test, but where am I when I run this test ?

4. Once the timer is running, you can minimize the form if you like. The timer will run anyway. .Is this another form besides my AutoA form I use for the off/on ?

When you click the button, you set the flag. When the timer event tests the flag and it is found to be SET, you can do nothing. Reset the Form.TimerInterval to 0. At this point your timer is quiescent.This part I think I can figure out.

As you can tell, I spend most of my time in modules and not with forms. LOL
 
1. If you have a button that actually DOES something when you click it, you have a class module associated with that form.

Every module, including a class module, has a declarations section. It is the part at the top of the module that begins with an "Option Compare ...." statement. It ends with "Option Explicit" (at least most of the time.)

In forms design mode, find the code icon on your iconic tool bar. Click that. Now press the following two keys simultaneously... <CTRL> and <HOME>.

OK, enter a couple of blank lines between the two option statements. Anything in between those statements is in the class module's general declaration area. So if you Dim something here, it is visible to ALL functions and subs in the class module.

To create a form-global state variable, Dim something in this spot.

e.g. Dim boState as Boolean

2. In the Form_Load code, you can do things like

Private Sub Form_Load

boState = FALSE
Me.TimerInterval = 60000 'This is 60 seconds...
'
' plus whatever else you wanted to do
'
End Sub


3. Build a form timer event in that same form, populate it with whatever you need...


Private Sub Form_Timer

If boState then
{do something}
Else
{do something else}
End If

End Sub

This code will run when the timer interval has been counted down. It is an event, so that means it won't run if another event is active at the same time. It will be deferred until that event releases control of the CPU.

Now, here is the primary consideration of this loop. If the timer loop is to keep on running (I'm assuming that you associated the boolean FALSE value for this), you must reload the interval.

If you want to stop the loop, load a 0 to the timer interval. The timer event will not trigger again.

4. Now this one threw me. Normally, if you are going to do something that runs in the background, it is always self-contained. I might have misled you. Perhaps the form should NOT be made invisible, but simply minimized, automatically or manually, so you could restore it and click the button that would flip-flop the Boolean state variable.
 

Users who are viewing this thread

Back
Top Bottom