Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In C#, where should I keep my timer's reference?

The documentation of System.Threading.Timer says that I should keep a live reference for it to avoid it being garbage collected. But where should I do that? My main is very simple that I don't know where to keep the reference:

class Program {
    static void Main() {
        new System.Threading.Thread(myThreadStart).Start();
        new System.Threading.Timer(myTimerCallback, new MyStateObject(), 0, 5000);
    }
}

I thought about keeping the reference in a static field in the Program class, assuming that static fields do not get collected until the end of the application. But I'm not sure this is the best way to do it, so I'd appreciate your advice.

like image 581
Hosam Aly Avatar asked Jan 25 '09 07:01

Hosam Aly


People also ask

What does |= mean in C?

The bitwise OR assignment operator ( |= ) uses the binary representation of both operands, does a bitwise OR operation on them and assigns the result to the variable.

What is ?: operator in C?

C operators are one of the features in C which has symbols that can be used to perform mathematical, relational, bitwise, conditional, or logical manipulations. The C programming language has a lot of built-in operators to perform various tasks as per the need of the program.

What does %d do in C?

In C programming language, %d and %i are format specifiers as where %d specifies the type of variable as decimal and %i specifies the type as integer. In usage terms, there is no difference in printf() function output while printing a number using %d or %i but using scanf the difference occurs.

What is -= in C?

This operator is a combination of '-' and '=' operators. This operator first subtracts the value on the right from the current value of the variable on left and then assigns the result to the variable on the left. Example: (a -= b) can be written as (a = a - b) If initially value stored in a is 8.


2 Answers

If your Timer is an application-level object there's nothing wrong with making it a private static member of your Main class. That's what I would do, anyway.

like image 134
gkrogers Avatar answered Nov 10 '22 07:11

gkrogers


EDIT: My original answer is rubbish. Really rubbish. I've kept it here to explain why it's rubbish though - it's in the comments, but they'd have been deleted with the answer.

GC.KeepAlive only makes sure a reference is treated as a root until after the call. In the code at the bottom of this answer, the GC.KeepAlive method would be called immediately, and then the timer would still be eligible for garbage collection. Because the newly created thread is a foreground thread, the app will run as long as it's alive (whereas the timer uses a background thread, which doesn't prevent program exit). This means that the Main method exits, but the application needs to keep running.

Arguably a simpler solution would be to run myThreadStart in the main thread, rather than creating a new one and then letting the main thread die. In other words, a simple solution would be:

using System.Threading;

class Program {
    static void Main() {
        Timer timer = new Timer(myTimerCallback, 
                                new MyStateObject(), 0, 5000);
        myThreadStart();
        GC.KeepAlive(timer);
    }
}

I assume the real code is more complicated though - in which case using a private static variable as suggested in other answers is probably the way to go. It really will depend on the usage though. I personally prefer not to create a static field just for the sake of preventing something being collected if there's an alternative (like the above) but sometimes it's virtually the only way of doing it.

Original (bad) answer:

If you really want to allocate it in Main, then you can use GC.KeepAlive:

using System.Threading;

class Program {
    static void Main() {
        new Thread(myThreadStart).Start();
        Timer timer = new Timer(myTimerCallback, 
                                new MyStateObject(), 0, 5000);
        GC.KeepAlive(timer);
    }
}
like image 36
Jon Skeet Avatar answered Nov 10 '22 08:11

Jon Skeet