Timer mystery - Forms.Timer vs. Threading.Timer
today I ran into a very interesting problem, which I was luckily able to solve very quickly, however I'd like to know the nature of the problem.
I wrote a control class that manages joystick actions. I wanted to start some action and start the timer on button click and after the timer interval to stop this action.
I have a class(pseudocode) that looks like this :
public class Joystick : UserControl
{
private Form.Timer timer; //or System.Threading.Timer
public void Init()
{
timer.Tick += new EventHandler(timerCallback) //Threading.Timer(timerCallback)
timer.Stop();//timer.Change(Timeout.Infinite, Timeout.Infinite);
}
public void ButtonCallback()
{
StartSomething();
timer.Stop();
timer.Start(); //timer.Change(500, Time开发者_运维知识库out.Infinite);
}
public void timerCallback()
{
StopSomething();
timer.Stop();//timer.Change(Timeout.Infinite, Timeout.Infinite);
}
}
I have two applications, one is really simple (just a form), second one is more complex, however behind this complexity is still an ordinary Form (well DotNetMagicForm) containing this UserControl. Managing code is in both applications absolutely the same, but in the more complex application the timerCallback() was never called. In the simple one everything worked fine. The init was called in both cases (breakpoint). Even if I assign the timerCallback in the ButtonCallback - the timerCallback still wasn't called.
I followed an advice of a colleague of mine and rewrote it by using Threading.Timer instead of Forms.Timer and suddenly it started working in both applications. Neither of us have a clue why it is.
I know my question is quite vague, but what could be the source of this issue?
Thanks
The Threading.Timer
does not use a UI message pump to callback the tick. It uses a ThreadPool
thread to do so.
The UI timers simply post messages to the form's message pump to solicit the callback. Your background magic form simply wasn't receiving these messages. I'm never sure why though, perhaps because the form is on another thread without a message pump, or inactive forms don't process the pump perhaps.
Have you had a look at this article comparing the different .NET timer classes
Windows Forms timer is suppose to send WM_TIMER to the message queue. Your message queue may be too busy with processing other windows messages or the message may not have been submitted in the first place. You might want to use a tool like Spy++ to figure out what happens (It should be installed as part of visual studio).
精彩评论