471,349 Members | 1,355 Online
Bytes | Software Development & Data Engineering Community
Post +

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 471,349 software developers and data experts.

Timer function doesn't listen to lock

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
Jul 16 '08 #1
12 4280
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
Jul 16 '08 #2
On Wed, 16 Jul 2008 14:25:54 -0700, Zytan <zy**********@gmail.comwrote:
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.
Your question is vague. But I'll make a guess.

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), 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. Any given thread, once it's successfully
obtained the lock, can reenter the same lock()-protected code arbitrarily
many times.

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.

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.

With that information, you could then successfully reason that the message
box is getting shown in the same thread each time, from which you could
then infer that the lock() statement isn't going to help. 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. :)

Pete
Jul 16 '08 #3
On Jul 16, 5:25*pm, Zytan <zytanlith...@gmail.comwrote:
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?

Jul 16 '08 #4
On Jul 16, 5:31*pm, Zytan <zytanlith...@gmail.comwrote:
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?
Jul 16 '08 #5
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
Jul 16 '08 #6
can you post your code?

Already found the error of my ways in another post! :)

Zytan

Jul 16 '08 #7
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

Jul 16 '08 #8
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
Jul 16 '08 #9
Zytan wrote:
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-

Jul 16 '08 #10
On Wed, 16 Jul 2008 14:46:25 -0700, Zytan <zy**********@gmail.comwrote:
[...]
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.
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, 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.

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.

Either way should be a workable solution.

And in another post:

On Wed, 16 Jul 2008 14:52:17 -0700, Zytan <zy**********@gmail.comwrote:
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. [...]
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.

In other words, pretty much anyone who's familiar with the same part of
the framework you're using could identify the same issue. I just happened
to be the first to note your question.

But regardless, I appreciate the comment, and of course you're welcome for
the help. :)

Pete
Jul 16 '08 #11
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

Jul 16 '08 #12
Zytan, you really should show some code. Then we will tell what you did
wrong (-:).
Pete already caught my mistake! But, thanks, nonetheless! :)

Zytan
Jul 16 '08 #13

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

3 posts views Thread by Mr. B | last post: by
3 posts views Thread by Nico Grubert | last post: by
4 posts views Thread by Naveen Mukkelli | last post: by
9 posts views Thread by Brett | last post: by
reply views Thread by XIAOLAOHU | last post: by

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.