How to use static variable to exit function? | | |
I have a function with a number of long loops. While the function is
running, I want to be able to click a Stop button and exit the function as
quickly as possible.
The abbreviated code looks like this:
[code in form frm1]
Private Sub cmdStart_Click
Call bas1.LongLoops(parameter1, parameter2, parameterN)
End Sub
[code in standard module bas1]
Public Function LongLoops(parameter1, parameter2, parameterN)
Do While i < 10000
[code omitted]
Loop
Do While i < 20000
[code omitted]
Loop
'etc, etc...
End Function
Should I use a static variable?
[code in form frm1]
Private Sub cmdStop_Click
blnStop = True
Call bas1.LongLoops(blnStop, parameter2, parameterN)
End Sub
[code in standard module bas1]
Public Function LongLoops(blnStop, parameter2, parameterN)
Static blnExit as Boolean
blnExit = blnStop
Do While i < 10000
If blnExit Then Exit Do
[code omitted]
Loop
Do While i < 20000
If blnExit Then Exit Do
[code omitted]
Loop
'etc, etc...
End Function
Or should I just raise an error that causes the function to exit?
[code in form frm1]
Private Sub cmdStop_Click
blnStop = True
Call bas1.LongLoops(blnStop, parameter2, parameterN)
End Sub
[code in standard module bas1]
Public Function LongLoops(blnStop, parameter2, parameterN)
If blnStop Then Err.Raise MYCUSTOMERROR
Do While i < 10000
[code omitted]
Loop
Do While i < 20000
[code omitted]
Loop
'etc, etc...
End Function
If I raise an error with a second call to the function, will the process
from the first call continue running?
Other options?
Thanks in advance. | | | | re: How to use static variable to exit function?
On Sat, 3 Sep 2005 16:08:49 -0700, "deko" <deko@nospam.com> wrote:
A quick-and-dirty solution would set a global variable to signal to
LongLoops to stop. If the code in bas1 is ONLY called from frm1, it
should be moved to the form, and a module-level global could be used.
A more elegant solution would perhaps test a public property in frm1
to check if the Stop button was clicked.
Don't forget to put a DoEvents in the LongLoops code, so the cmdStop
click would happen while it is executing. If you were using a "tight"
loop, it would first execute and THEN the click would occur - a little
too late.
I think raising an error is the wrong thing to do. It's abusing an
error handler feature for something it was not designed for.
-Tom.
[color=blue]
>I have a function with a number of long loops. While the function is
>running, I want to be able to click a Stop button and exit the function as
>quickly as possible.
>
>The abbreviated code looks like this:
>
>[code in form frm1]
>Private Sub cmdStart_Click
> Call bas1.LongLoops(parameter1, parameter2, parameterN)
>End Sub
>
>[code in standard module bas1]
>Public Function LongLoops(parameter1, parameter2, parameterN)
> Do While i < 10000
> [code omitted]
> Loop
> Do While i < 20000
> [code omitted]
> Loop
> 'etc, etc...
>End Function
>
>Should I use a static variable?
>
>[code in form frm1]
>Private Sub cmdStop_Click
> blnStop = True
> Call bas1.LongLoops(blnStop, parameter2, parameterN)
>End Sub
>
>[code in standard module bas1]
>Public Function LongLoops(blnStop, parameter2, parameterN)
> Static blnExit as Boolean
> blnExit = blnStop
> Do While i < 10000
> If blnExit Then Exit Do
> [code omitted]
> Loop
> Do While i < 20000
> If blnExit Then Exit Do
> [code omitted]
> Loop
> 'etc, etc...
>End Function
>
>Or should I just raise an error that causes the function to exit?
>
>[code in form frm1]
>Private Sub cmdStop_Click
> blnStop = True
> Call bas1.LongLoops(blnStop, parameter2, parameterN)
>End Sub
>
>[code in standard module bas1]
>Public Function LongLoops(blnStop, parameter2, parameterN)
> If blnStop Then Err.Raise MYCUSTOMERROR
> Do While i < 10000
> [code omitted]
> Loop
> Do While i < 20000
> [code omitted]
> Loop
> 'etc, etc...
>End Function
>
>If I raise an error with a second call to the function, will the process
>from the first call continue running?
>
>Other options?
>
>Thanks in advance.
>[/color] | | | | re: How to use static variable to exit function?
> A quick-and-dirty solution would set a global variable to signal to[color=blue]
> LongLoops to stop.[/color]
sounds interesting.
[color=blue]
> If the code in bas1 is ONLY called from frm1, it
> should be moved to the form, and a module-level global could be used.[/color]
It is, but there's so much code it needs to be segregated by purpose.
[color=blue]
> A more elegant solution would perhaps test a public property in frm1
> to check if the Stop button was clicked.
>
> Don't forget to put a DoEvents in the LongLoops code, so the cmdStop
> click would happen while it is executing. If you were using a "tight"
> loop, it would first execute and THEN the click would occur - a little
> too late.[/color]
10-4
[color=blue]
> I think raising an error is the wrong thing to do. It's abusing an
> error handler feature for something it was not designed for.[/color]
perhaps...
Here's what I've got working:
[code in form frm1]
Private Sub cmdStart_Click
Call bas1.LongLoops(False, parameter2, parameterN)
End Sub
Private Sub cmdStop_Click
Call bas1.LongLoops(True)
End Sub
[code in standard module bas1]
Public Function LongLoops(blnStop As Boolean, Optional parameter2, Optional
parameterN)
Static blnExit As Boolean
blnExit = blnStop
Do While i < 10000
If blnExit Then Exit Do
DoEvents
[code omitted]
Loop
Do While i < 20000
If blnExit Then Exit Do
DoEvents
[code omitted]
Loop
[code omited]
End Function
The problem (what I thought might be avoided by raising an error) is that I
have to instantiate a bunch of objects to get into the loop (on the second
call made from cmdStop).
This does not work:
[code in standard module bas1]
Public Function LongLoops(blnStop As Boolean, Optional parameter2, Optional
parameterN)
Static blnExit As Boolean
blnExit = blnStop
If Not blnStop Then
Set obj1 = Object1
Set obj2 = Object2
Set objN = Object N
Do While obj1 < obj2
If blnExit Then Exit Do
DoEvents
Test objN
[code omitted]
Loop
End If
End Function
The reason this does not work is because (as this new example indicates) the
actual code uses objects rather than integers in the looping construct.
So the objects have to be set to get into the loop. So the second call
needs to get into the loop or blnExit does not change - which I find strange
because I thought I didn't need to get into the loop since blnExit is
Static. That is, I thought just getting into the function with the second
call and changing the value of the Static variable (without getting into the
loop) would cause the Static variable to change regardless of where it is
being used.
Perhaps this would be the case with a global variable? That would be better
because I wouldn't have to instantiate all those objects (just to get into
the loop so I can exit it). But perhaps I could use some Resume Next
statements If blnStop = True or something...
Anyway, thanks for the reply. | | | | re: How to use static variable to exit function?
The last time I played with this type of thing, I finished up having to
"break-out" of the executing function. I did this in rather elegant style
by throwing a message box every 20 loops asking if I wanted to continue or
not. I'm just wondering if a refinement on that is to breakout to a
function that tests the public variable.
if TestLoop = 20 then
If BreakOut() Then Exit Do
...
Function Breakout() as boolean
BreakOut = PublicStop
End Function
Then from your form ....
Private Sub cmdStop_Click
PublicStop = True
Endsub
The only thing I'm not sure of is whether the button on the form can alter
the public while your LongLoops is executing. If not, well, elegance is
worth pursuing!
--
Regards,
Kevin
"deko" <deko@nospam.com> wrote in message
news:Q8qdnZ2dnZ0Y4qSMnZ2dnSJrht6dnZ2dRVn-yp2dnZ0@comcast.com...[color=blue]
> A quick-and-dirty solution would set a global variable to signal to
> LongLoops to stop.[/color]
sounds interesting.
[color=blue]
> If the code in bas1 is ONLY called from frm1, it
> should be moved to the form, and a module-level global could be used.[/color]
It is, but there's so much code it needs to be segregated by purpose.
[color=blue]
> A more elegant solution would perhaps test a public property in frm1
> to check if the Stop button was clicked.
>
> Don't forget to put a DoEvents in the LongLoops code, so the cmdStop
> click would happen while it is executing. If you were using a "tight"
> loop, it would first execute and THEN the click would occur - a little
> too late.[/color]
10-4
[color=blue]
> I think raising an error is the wrong thing to do. It's abusing an
> error handler feature for something it was not designed for.[/color]
perhaps...
Here's what I've got working:
[code in form frm1]
Private Sub cmdStart_Click
Call bas1.LongLoops(False, parameter2, parameterN)
End Sub
Private Sub cmdStop_Click
Call bas1.LongLoops(True)
End Sub
[code in standard module bas1]
Public Function LongLoops(blnStop As Boolean, Optional parameter2, Optional
parameterN)
Static blnExit As Boolean
blnExit = blnStop
Do While i < 10000
If blnExit Then Exit Do
DoEvents
[code omitted]
Loop
Do While i < 20000
If blnExit Then Exit Do
DoEvents
[code omitted]
Loop
[code omited]
End Function
The problem (what I thought might be avoided by raising an error) is that I
have to instantiate a bunch of objects to get into the loop (on the second
call made from cmdStop).
This does not work:
[code in standard module bas1]
Public Function LongLoops(blnStop As Boolean, Optional parameter2, Optional
parameterN)
Static blnExit As Boolean
blnExit = blnStop
If Not blnStop Then
Set obj1 = Object1
Set obj2 = Object2
Set objN = Object N
Do While obj1 < obj2
If blnExit Then Exit Do
DoEvents
Test objN
[code omitted]
Loop
End If
End Function
The reason this does not work is because (as this new example indicates) the
actual code uses objects rather than integers in the looping construct.
So the objects have to be set to get into the loop. So the second call
needs to get into the loop or blnExit does not change - which I find strange
because I thought I didn't need to get into the loop since blnExit is
Static. That is, I thought just getting into the function with the second
call and changing the value of the Static variable (without getting into the
loop) would cause the Static variable to change regardless of where it is
being used.
Perhaps this would be the case with a global variable? That would be better
because I wouldn't have to instantiate all those objects (just to get into
the loop so I can exit it). But perhaps I could use some Resume Next
statements If blnStop = True or something...
Anyway, thanks for the reply. | | | | re: How to use static variable to exit function?
deko wrote:[color=blue]
> I have a function with a number of long loops. While the function is
> running, I want to be able to click a Stop button and exit the function as
> quickly as possible.[/color]
[color=blue]
> Other options?[/color]
Wrap the whole shebang in a class. Everything is in one place, shielded
from outside influence and re-usable.
'<clsDekoLoop>
Option Compare Database
Option Explicit
Private WithEvents btnStop As Access.CommandButton
Private exitLoop As Boolean
Private mElapsedTime As String
Public Property Get ElapsedTime() As String
ElapsedTime = mElapsedTime
End Property
Public Sub Init(btn As Access.CommandButton)
Set btnStop = btn
btnStop.OnClick = "[Event Procedure]"
End Sub
Private Sub btnStop_Click()
exitLoop = True
End Sub
Public Sub RunLoop(outerLoop As Long, innerLoop As Long)
Dim x As Long
Dim y As Long
Dim b As Single
b = Timer
For x = 1 To outerLoop
DoEvents
For y = 1 To innerLoop: Next
If exitLoop Then Exit For
Next
mElapsedTime = "Outer Loop: " & x & vbCrLf & _
"Elapsed time: " & Timer - b
End Sub
Private Sub Class_Terminate()
If Not btnStop Is Nothing Then Set btnStop = Nothing
End Sub
'</clsDekoLoop>
'<frmTestDekoLoop>
CommandButton: cmdStart
Command Button: cmdStop
Private Sub cmdStart_Click()
Call TestDekoLoop
End Sub
Sub TestDekoLoop()
Dim dl As clsDekoLoop
Set dl = New clsDekoLoop
dl.Init Me.cmdStop
dl.RunLoop 10000, 1000
MsgBox dl.ElapsedTime
Set dl = Nothing
End Sub
'</frmTestDekoLoop> | | | | re: How to use static variable to exit function?
> Wrap the whole shebang in a class. Everything is in one place, shielded[color=blue]
> from outside influence and re-usable.[/color]
I was exploring that idea yesterday, but got things working... other fish to
fry now.
Any error generated by LongLoops is passed back to cmdStop_Click. So with
an 'OnError Resume Next' statement in the calling sub, the program flow
continues into the loop (with blnExit set to True) and the loops exit.
Private Sub cmdStop_Click
OnError Resume Next 'mainly concerned with Error 91
Call bas1.LongLoops(True)
End Sub
Public Function LongLoops(blnStop As Boolean, Optional parameter2, Optional
parameterN)
Static blnExit As Boolean
blnExit = blnStop
Set obj1 = Object1
Set obj2 = Object2
Set objN = Object N
Do While obj1 < obj2
If blnExit Then Exit Do
DoEvents
Test objN
[code omitted]
Loop
End Function
I'm still wondering why I have to enter the loop with the second call - I
thought a Static variable would change value everywhere in the function once
it's passed to the function. | | | | re: How to use static variable to exit function?
deko wrote:
[color=blue]
> So the objects have to be set to get into the loop. So the second call
> needs to get into the loop or blnExit does not change - which I find strange
> because I thought I didn't need to get into the loop since blnExit is
> Static. That is, I thought just getting into the function with the second
> call and changing the value of the Static variable (without getting into the
> loop) would cause the Static variable to change regardless of where it is
> being used.
>
> Perhaps this would be the case with a global variable? That would be better
> because I wouldn't have to instantiate all those objects (just to get into
> the loop so I can exit it). But perhaps I could use some Resume Next
> statements If blnStop = True or something...[/color]
I think the problem is that when you execute the procedure again while
the first call is still running the second call has to run to completion
before the first call can resume running. Frankly I am surprised the
whole thing doesn't just blow up in your face. The second thing that
isn't clear is what does it mean for one object to be less than another
object. One object is equal to another object when they both reference
the same instance.
Any way if you intent on doing this your way, try checking blnExit
immediatley after assigning it and exiting the function right then
if true.
blnExit = blnStop
If blnExit Then Exit Function | | | | re: How to use static variable to exit function?
> blnExit = blnStop[color=blue]
> If blnExit Then Exit Function[/color]
I need the loops to complete because they call other functions (there are a
few, and I don't know which one the code will be in when the user clicks the
Stop button) - then the normal flow of the procedure will continue to the
end.
It's working fine. My only confusion was dealing with the Static Boolean
variable.
As for the objects being greater or less than each other, that example was
just to keep things concise. The point is the loops require objects (one of
which is a collection) to be instantiated. |  | Similar Microsoft Access / VBA bytes | | | /bytes/about
We are a network of experts and professionals in IT and software development that help one another with answers to tough questions and share insights.
Get the best answers to your questions from over 226,439 network members.
|