System.Threading.Timer Not Starting?
Asked Answered
T

1

8

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?

Tanganyika answered 3/10, 2012 at 15:39 Comment(3)
What does "hung on a message" mean? Doesn't look like statement where anything can get stuck.Stayathome
Don't debug with labels. Look for System.Diagnostics.Debug.Print() and collect more info.Stayathome
@Henk Holterman, terminology is incorrect, then. "Program stops because it's not running anything else, not because anything is blocking." I felt "hang" would be more concise, though I do understand it has a different connotation to it. As to using Debug.Print instead of labels: in general I agree, though since I did not know before this point where the application stopped or if I'd have access to what was printed once it stopped, I needed something that updated on screen. Thank you for the tip, though.Tanganyika
Z
10

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.

Zahavi answered 3/10, 2012 at 15:55 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.