Post by Michael CGranted I don't understand what's going on under the hood but that is part
of the problem.
IMHO, it's poor practice to denigrate a language feature if you don't
fully understand it.
Post by Michael CAs I said previously it must compile to a seperate function
but contains another functions local variables. I say again Yuk!
And I say "Aha!" Variable capturing is one of the things that makes
anonymous methods so useful.
Post by Michael CPost by Peter DunihoNegative. An anonymous method doesn't have any of the re-entrancy issues
that calling DoEvents() does.
I don't see how you can say that. The only way mine can be re-entrant is if
the user clicks the GO button again.
Actually, it's re-entrant the moment you call DoEvents(). "Under the
hood", you've got a window's "window proc" (aka "wndproc") that is busy
handling a specific window message, having been called from a message pump
loop. When you call DoEvents(), that enters an entirely new message pump
loop, which will in turn call the window proc again.
Just because you don't see the re-entrancy, that doesn't mean it doesn't
exist, nor does it mean there's no potential for a problem. The user
clicking the same button again isn't the issue, and in fact I would expect
that a proper program would disable the button if it's inappropriate for
it to be clicked. It's the question of the fact that your window hasn't
finished handling one window message, and now may be asked to process any
number of new window messages.
It's an intractable design problem inherent in calling DoEvents(). It
leads to code that is at best difficult to maintain, and at worst can
contain subtle bugs that are difficult to find, never mind solve.
Post by Michael CYours suffers the same problem as far
as I can see as someone can kick off the entire process again if they like.
Mine ensures that the Form class is handling one message at a time. You
can always _add_ re-entrancy to the code, but it's not inherent in the
anonymous method technique, while it is inherent in using DoEvents().
Post by Michael CFrom the programmers pov doevents is quite simple. While your method isn't
much more complicated it still is.
DoEvents() only _seems_ to be simple. The fact that you believe it
actually _is_ simple is a symptom of the basic problem. DoEvents() has
fooled you into thinking that it's simple, when in fact it's actually
quite a complicated addition to the architecture.
Post by Michael CBTW, who said anything about DoEvents. It was you who added the idea of
using DoEvents. And who said anything about a GUI, this is a windows
service.
I can only laugh at this point. It appears that I missed an important
aspect of the original question (it's a service), and you missed an
important aspect of my reply: I used the System.Windows.Forms.Timer class
in a context where that class isn't useful or desirable at all.
That said, consider "GUI" as a general talking point if you will. The
issue here is whether the thread is available to process other activity.
You wrote "You can't sleep for 60 seconds because your service won't stop
for 60 seconds if someone pushes stop", so obviously you anticipate doing
_something_ inside that loop that allows the service to process other
input.
Whether that something is DoEvents() or something else, the same basic
issues apply though I agree that some specifics that apply to DoEvents()
obviously wouldn't in other implementations. In particular, there are
still re-entrancy issues and depending on the architecture of the service
they could be even more complex than those introduced by the use of
DoEvents() in a Forms application.
Now, in the context of a service, timers get more complicated than when
using System.Windows.Forms.Timer in a Forms application. All of what I
wrote was aimed specifically at a Forms application, and that's where the
System.Windows.Forms.Timer class is especially helpful. It ensures that
execution of the timer event handler is synchronized with other activity
in the GUI thread. Obviously that benefit doesn't apply when using some
other timer mechanism.
Because of that, in this situation my recommendation would be to run the
"retry" logic on a different thread, per my alternate suggestion in my
original reply.
There is still no need, nor is it desirable, to have any thread wait 60
seconds by actually waiting for 1 second 60 times. Just make the thread
wait 60 seconds and be done with it. If the process needs to be available
to do other work, handle that other work in a different thread.
Pete