Article View: comp.lang.pascal.delphi.misc
Article #71TechTips: Avoiding unavoidable recursion in event-handlers ...
From: Sundial Services
Date: Mon, 06 Dec 1999 00:00
Date: Mon, 06 Dec 1999 00:00
74 lines
4342 bytes
4342 bytes
Delphi works its apparent magic by a series of event-handlers. Every
component, visible and non-visible, has a series of event-properties
which allow you to intercept these events as they occur. Other key
Delphi features such as the "inherited" statement, the ability to create
subclassed descendents of toolbar components and even of other forms in
your application, are the key to Delphi's power -- but also put many of
the interactions that DO take place in your application quite out of
sight. This can make them tough to debug sometimes.
To make a long TechTip short, however, let's focus on one of the more
troublesome problems: recursion. This is where something that you are
doing inside an event-handler might cause the same event to occur. This
causes your event-handler to be entered recursively (which Delphi
certainly supports...), whereupon the nefarious cycle begins again until
the stack is blown and the application (or the system) crashes.
Whether or not recursion will occur in your case depends entirely upon
you and what you're doing. The question before the house is simply, how
can we keep it from getting in the way? The answer is simple.
(1) Define a boolean variable, in the "private" section of your class
declaration. Let's call it "recursionLock." You might have several of
these, depending upon how many potentially-recursive paths you have.
Notice that this must not be a *local* variable, nor should it be
*global.*
(2) Now for your method-code. Modify it like this:
method ...
...
begin
if RecursionLock then exit;
try
RecursionLock := true;
<< original method code goes here >>
finally
RecursionLock := false;
end;
end;
(3) You know from the outset that "recursionLock" will be initially
false, because every byte of a new object is initialized to zero (false)
by Delphi. So you don't have to initialize it that way.
(4) Now, the first instance of the method will find the lock is open, go
right inside, and shut the lock behind him. Any other recursion through
the routine will find the lock is closed and simply exit. The recursion
takes place, as it must, but it does no harm.
(5) The "try..finally" block is essential. It guarantees that, even if
an exception occurs, and even if you "exit" or "break" out of the block,
the "finally" part will be executed.
(6) Naturally, you must do nothing before the "try" part, or in the
"finally" part, that would cause recursion.
This technique is useful for other things, too -- like "CalcFields"
routines. Calculated fields are wonderful things but they go off like
your next door neighbor's car-alarm ... anytime day or night, even when
you don't want them to or need them to. (Really you only need a
calculated field to go off when you're about to display the value
someplace.) A "CalcFields" routine can examine the flag to realize when
it's got a "phony call," and simply exit. This routine would not set
the flag, nor reset it, but simply notice when it is currently set.
HTH! :-)
----------------------------------------------------------------------
Sundial Services :: Scottsdale, AZ (USA) :: (480) 946-8259
mailto:info@sundialservices.com (PGP public key available.)
> High-speed, script-driven, table repair/support for Paradox/BDE...
> ChimneySweep{tm}: "Click click, it's fixed!" {tm}
> http://www.sundialservices.com/cs3web.htm
Technical Details
Message-ID:
<384BDF64.10D8@sundialservices.com>Path:
arc1-ca.pugleaf.net!unknown!not-for-mailShow Full Headers
Complete Article Headers
X-Google-Language: ENGLISH,ASCII-7-bit X-Google-Thread: ffff5,621456c0b23430b,start X-Google-Attributes: gidffff5,public X-Google-Thread: ff75c,621456c0b23430b,start X-Google-Attributes: gidff75c,public X-Google-Thread: 10baee,621456c0b23430b,start X-Google-Attributes: gid10baee,public From: Sundial Services <info@sundialservices.com> Subject: TechTips: Avoiding unavoidable recursion in event-handlers ... Date: 1999/12/06 Message-ID: <384BDF64.10D8@sundialservices.com> X-Deja-AN: 557300321 Content-Transfer-Encoding: 7bit Content-Type: text/plain; charset=us-ascii X-Complaints-To: abuse@prserv.net X-Trace: 6 Dec 1999 16:08:21 GMT, 32.101.171.56 Organization: Sundial Services MIME-Version: 1.0 Reply-To: info@sundialservices.com Newsgroups: comp.lang.pascal.delphi.misc,comp.lang.pascal.delphi.databases,borland.public.delphi.database.desktop