views:

68

answers:

1

I've just written some code to perform a timeout action if an asynchronous task takes too long to process, but what is not clear to me is if and when the timeout instance will ever be disposed of (I think it will in the case where the asynchronous task completes in a timely fashion, but otherwise I've got no idea), or if I'm going to be accumulating instances every time I call this code.

//StartNew creates a new instance of System.Timers.Timer, and 
//  invokes the ActionOnTimeout after 2000ms, unless calling code
//  calls "Stop" first
var timeout = ProcessTimeout.StartNew(() => ActionOnTimeout(), 2000);

//DoAsyncTask creates a new thread, does potentially slow stuff, 
///   then invokes this callback
DoAsyncTask(() => 
    {
         if(timeout.Running)
         {
             timeout.Stop();
             DoCallbackStuff();
         }
    });

(If it's any help, the ProcessTimeout class uses a System.Timers.Timer)

A: 

It's not clear what timeout is here or what DoAsyncTask does, but a few general points:

  • Your lambda expression will capture the timeout variable. It won't capture the value of the variable... so if you have something else later in the same method which sets timeout to null or a different value, the original value won't be held in the lambda expression.
  • The lambda expression will prevent whatever timeout refers to from being garbage collected, so long as the delegate itself isn't eligible for garbage collection
  • Garbage collection isn't the same as disposal. You talk of "when the timeout instance will ever be disposed of" - what's calling Dispose? That won't be affected by the garbage collector, unless you're relying on a finalizer calling Dispose for you.
Jon Skeet
Thanks @Jon, I didn't want to copy in all the code, so I've added some comments on timeout and DoAsyncTask. You're right of course, about GC and disposal, though I admit that I tend to confuse the two (to answer your question, nobody's calling `Dispose` - yet). The three references to timeout in this snippet are the only places it is used.
Benjol
Hm, so the question now becomes, what will prevent the delegate from being garbage collected? I guess if DoAsyncTask *never* returns there's no hope (I can cope with that), but what if it returns 'too late'?
Benjol
@Jon Skeet: If a scope contains three local variables, two of which are used in each of two lambda expressions (one of them is used in both), and delegate from one of the lambda expressions is held indefinitely, will the variable that wasn't used in that lambda expression continue to be held, or will the variables be held separately?
supercat
@supercat: I believe the variables will all be held in one synthetic type.
Jon Skeet