I need a timer to display seconds on my form and simultaneously trigger some events every 10 sec. The events in question involve checking for certain configurations in the input stream after the records are put in a few tables.
My form's face is totaly inaccessible. I have a TabControl with the first TabPage covering the entire form. Therefore I set up a Label to display hh::mm::ss values on the first Page inside a GroupBox.
The problem is that the timer stops and its behavior is so chaotic that it is hard to describe the full range. Occasionally it runs nonstop for a few minutes until I close the form. At other times it displays only one value then stops. If I change TabPages it will almost certainly stop but not always. Just once I observed an exception. It almost certainly stops if I move the Console Window away from the form.
What is the problem
The code is as follows. I essentially copied MSDN samples and made simple changes when needed.
class TimerClass
{
public void createTimer ( )
{
AutoResetEvent autoEvent = new AutoResetEvent ( false );
StatusChecker statusChecker = new StatusChecker ( 10 );
TimerCallback timerDelegate = new TimerCallback ( statusChecker.CheckStatus );
System.Threading.Timer stateTimer = new System.Threading.Timer ( timerDelegate, autoEvent, 1000, 1000 );
} // createTimer
} // TimerClass
class StatusChecker
{
int invokeCount, maxCount;
public StatusChecker ( int count )
{
invokeCount = 0;
maxCount = count;
}
public void CheckStatus ( Object stateInfo )
{
AutoResetEvent autoEvent = ( AutoResetEvent ) stateInfo;
++invokeCount;
Console.WriteLine ( DateTime.Now.ToString ( "h:mm:ss" ) );
SetControlText ( Globals.tLabTimerPg1, DateTime.Now.ToString ( "h:mm:ss" ) );
if ( invokeCount == maxCount )
{
invokeCount = 0;
autoEvent.Set ( );
Console.WriteLine ( "Ten Sec" );
// gets in this block every 10 sec.
}
} // CheckStatus
private void SetControlText ( System.Windows.Forms.Control clr, String text )
{
if ( clr.InvokeRequired )
{
clr.BeginInvoke ( ( MethodInvoker )delegate ( )
{
SetControlText ( clr, text );
} );
}
else
{
clr.Text = text;
}
} // SetControlText
} // class StatusChecker
The Timer Class is invoked in Form1_Load event handler via the following code:
Globals.tLabTimerPg1 = this.tLabTimePg1; // the Label is assigned to a global variable
TimerClass tmrCl = new TimerClass ( );
ThreadStart trSt = new ThreadStart ( tmrCl.createTimer );
Thread trd = new Thread ( trSt, 5000 );
trd.Name = "timer10";
trd.SetApartmentState ( ApartmentState.MTA );
trd.Start ( );
Many thanks.

Timer event unstable
Shepherd
If you're looking at a timer granularity of 1000 ms (1 second) and want to update something on a form in response to the timer elapsed/tick event, I would suggest using the System.Windows.Forms.Timer instead. You don't need to do the whole InvokeRequired dance with that class's event handler and you don't need a background thread at all. Also, regardless of the timer you use, it won't be exact. If you're looking to have something occur every 10 seconds but you'e having an event raised every 1 second, you increase your percent error by 10 times. I would suggest creating a timer with 10000 ms instead of 1000 ms and tracking every 10 events...
Using System.Windows.Forms.Timer you can distill your example down to this:
public class MyForm : Form
{
Timer timer = new Timer();
// ...
private void MyForm_Load(object sender, EventArgs e)
{
timer.Tick += new EventHandler(timer_Tick);
timer.Interval = 10000;
timer.Start();
}
private void timer_Tick(object sender, EventArgs e)
{
myControl.Text = DateTime.Now.ToString ( "h:mm:ss" );
}
}
And, in fact, the processing of creating the timer object and setting it's properties can be done entirely with the WinForms designer...
Shinny
Thank you very much, Peter. It is plenty.