Timer function doesn't listen to lock

Z

Zytan

I have a Timer class set to trigger every second. The Tick function
that is called every second uses a lock to prevent multiple ticks from
executing the same code at the same time. The code within calls a
Visual Basic input message box, which is synchronous, it waits until
you enter some input, and press enter. But, this message box pops up
every second regardless if the old ones have finished. The timer's
Tick function is called over and over, and runs the code in the lock,
totally ignoring the lock. Why? Something to do with threads? But,
that's just what locks are FOR. The lock variable = new object(), so
it should be fine.

Zytan
 
Z

Zytan

Btw, I'm using System.Windows.Forms.Timer.

Should I just use System.Timers.Timer, instead, and use
Timer.AutoReset, to make the time tick ONLY once, and I'll start it up
again after it ticks? (That should be a solution, but I'd still like
to know what is going on with the lock that's not working above......)

Zytan
 
I

Ignacio Machin ( .NET/ C# MVP )

I have a Timer class set to trigger every second.  The Tick function
that is called every second uses a lock to prevent multiple ticks from
executing the same code at the same time.  The code within calls a
Visual Basic input message box, which is synchronous, it waits until
you enter some input, and press enter.  But, this message box pops up
every second regardless if the old ones have finished.  The timer's
Tick function is called over and over, and runs the code in the lock,
totally ignoring the lock.  Why?  Something to do with threads?  But,
that's just what locks are FOR.  The lock variable = new object(), so
it should be fine.

Zytan

Hi,

You cannot call a UI from a thread other than the UI. Are you using
Control.Invoke?
 
I

Ignacio Machin ( .NET/ C# MVP )

Btw, I'm using System.Windows.Forms.Timer.

Should I just use System.Timers.Timer, instead, and use
Timer.AutoReset, to make the time tick ONLY once, and I'll start it up
again after it ticks?  (That should be a solution, but I'd still like
to know what is going on with the lock that's not working above......)

Zytan

can you post your code?
 
Z

Zytan

Whatever timer class you're using (there are no less than three in .NET
and you're not specific about which one you're using...I'm guessing
System.Windows.Forms.Timer, since that one I know off the top of my head
has a Tick event),
Yes.

undoubtedly the Tick event is being raised on the same
thread each time. The lock() statement only prevents multiple threads
from entering the same code.

Ah, of COURSE!
Thank you.
If you don't want the message box displayed with each tick of the timer,
just disable the timer before you show the message box and reenable it
when the message box is dismissed. You can't use lock() for the purpose
you're trying to use it for.

Exactly. I already knew the solution, it just bugged me that I
couldn't figure out why lock() wasn't working. But, it's the same
thread, of course!!

In fact, the other Timer classes are better, since you can get them to
'tick' just once, I believe, so there's absolutely NO chance of it
ticking twice, so you can make sure to do the work first, and then
restart it after.
For future reference, the debugger is a great way to explore what's
actually going on. For example, in this particular case, you could have
just set a breakpoint where you show the message box. Then, the second
time you hit the breakpoint, you could look at the call stack. At that
point, you'd find that in the same call stack was the previous call that
showed the message box.

I use the debugger quite often, but this information wouldn't have
made me realize my error, since I would have expected the same call
stack. I just wasn't thinking that the same thread doesn't listen to
locks. Stupid.
Even if you
were a bit uncertain about the rules for how lock() works, just knowing
what was actually going on would probably have given you that "aha!"
moment needed to figure things out. :)

Good point! :)

Zytan
 
Z

Zytan

You cannot call a UI from a thread other than the UI. Are you using
Control.Invoke?

Nope, I was just NOT realizing that lock() will not prevent the SAME
THREAD from getting into it....... I should know this since I've done
recursion with locks, and I've been bitten by this before.

Zytan
 
Z

Zytan

Pete, I just had to write again to thank you. You have no idea how
much TIME you are saving me and how useful you're replies are.
Sometimes little bugs like this, even though I should know better, can
take up a good half hour or more, sometimes several hours, and stress
and frustration, so I appreciate the time you spend to clear up these
little matters. All the best, and have a great day! :)

Zytan
 
H

henk holterman

Zytan said:
I have a Timer class set to trigger every second. ...



Zytan, you really should show some code. Then we will tell what you did
wrong (-:).

-hh-
 
Z

Zytan

If you know you always specifically need a "one-shot" timer, yes...I'd
agree. They do, of course, introduce the complication of being raised on
a different thread

Yes, I noticed that, since I was updating GUI controls in the tick
handler. I don't think this will pose a problem, though. Thanks for
the warning.
, but it's possible that in your case, you don't
actually need the single-threaded behavior of the Forms.Timer class, or
that you feel that having to use Control.Invoke() is a suitable trade-off
for getting more deterministic timer behavior.

I have no issues using Control.Invoke(), I am comfortable with it.
That said, with a one-second interval, assuming you disable the timer the
moment the event is raised, I doubt there's any realistic chance of the
timer getting to be raised more than once, assuming you're not already
abusing the GUI thread. Even if there was a chance, a simple boolean flag
would suffice to protect the handling of the event, by allowing you to
simply ignore re-entrant ticks of the timer.

Very true.
You're very welcome. For what it's worth, I think a lot of times it's
just a matter of having someone else look at the problem. Often the only
reason a person's having a problem is that they are too close to the
implementation to see the mistake. They already know exactly what they
_meant_ for it to do, making it difficult or impossible to see what it
actually does.

Yup, just like when you read an essay you wrote yourself, you tend to
read what you MEANT to write, and not what you actually wrote, so a
second set of eyes are a godsend.

Thanks again!

Zytan
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top