Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

System.Threading.Timer Not Starting?

I'm using C# with Compact Framework 2, SP2.

The device's OS was set up to start up with my application, let's call the application "Loader.exe."

Loader is simply this: a single, plain form that shows status messages throughout loading, if necessary (layman's terms for there being an error and an exception message, or "starting application [xyz]"), and a state machine running in the background while a basic full-screen form is shown.

So Loader's form's constructor has the following at the very end:

try
{
    label1.Text = "Starting GUI Init Thread...";  //debug only message
    System.Threading.Timer guiInit = new System.Threading.Timer(
        RunStateMachine, null, 2000, System.Threading.Timeout.Infinite
        );
    //callback: RunStateMachine, null argument
    //initial callback is 2000ms from this point, and doesn't run again.
}
catch (Exception ex1)
{
    label1.Text = "GUI Init Error 2";
    Failure_Label.Text = ex1.Message;
}

And "RunStateMachine" does work on a different thread than the UI, allowing the form to display, and any time RunStateMachine needs to interact with the form, such as updating messages, I call a function that uses if(this.InvokeRequired){this.Invoke(...);} else{...}

So, my problem?
Intermittently, my program will hang, and it's because the timer didn't trigger a callback. I added in the debug message in the try block above, along with MANY other places to tell me where it hung up, including a message at the VERY start of "RunStateMachine." Eventually, my program hung on the message "Starting GUI Init Thread..."

This tells me that the thread timer is not running the one time I need it to.
My theory is that it's being garbage collected prior to the timer triggering the callback. That would mean if the timer was global, and then disposed explicitly when I get to RunStateMachine, that it will run perfectly... but I don't want to think I solved it just to find this coming up intermittently a month from now.

Thoughts?

like image 403
Peter Lacerenza Avatar asked Oct 03 '12 15:10

Peter Lacerenza


1 Answers

My theory is that it's being garbage collected prior to the timer triggering the callback. That would mean if the timer was global, and then disposed explicitly when I get to RunStateMachine, that it will run perfectly... but I don't want to think I solved it just to find this coming up intermittently a month from now.

It looks like you want confirmation that this is your problem. Yes, this is the problem.

The timer is stored in a local variable which is never used ever again. This makes it eligible for GC. The GC'ing of the Timer leads to finalization leading to the timer to be disabled.

I suggest you store the timer in an instance field of your form class and remove it from there once the callback has fired.

like image 92
usr Avatar answered Oct 03 '22 05:10

usr