I have a simple class:
public class Runner
{
public void RunAndForget(RunDelegate method)
{
ThreadPool.QueueUserWorkItem(new WaitCallback(Run), method);
}
private void Run(object o)
{
((RunDelegate )o).Invoke();
}
}
And if I use this like so:
private void RunSomethingASync()
{
Runner runner = new Runner();
runner.FireAndForget(new RunDelegate(Something));
}
Is there any danger using it like this? My C++ guts tell me that runner object should be destroyed after RunSomethingASync is finished. Am I right? What happens then to the method running on different thread?
Or perhaps it is other way around and runner will not be collected? That would be a problem considering I may call RunSomethingASync() many times.
In short, no. .NET garbage collection is not done on a deterministic basis. An object is eligible for garbage collection once it is no longer rooted – that is, once no more reference paths to it (from living objects) exist. There is no guarantee that any particular object — or, indeed, any object at all — will ever be garbage collected, though it’s pretty likely.
However, in your case, your object isn’t even eligible. While the object is falling out of scope in your code (so it would appear that no references exist), delegates do contain references to their owning instance (assuming they point to an instance method). A reference to your object will exist until
Runis called, as theThreadPoolis holding on to a reference to the delegate until then, and that delegate has a reference toRunner.So, to answer your question, there is no danger in what you’re doing. Because the delegate references the instance, your object cannot and will not be collected until after your operation completes. Once it completes, your object will then be eligible.