views:

63

answers:

3

I'm looking for something nice and simple. For example:

RunAfter(3, delegate() { z = 5; }); // run after 3 seconds
FnThatTakes5Seconds();

In my cases I want to test some threading code and have something happen in the middle of another function call.

A: 

I would use a System.Threading.Timer that only fires once and starts immediately.

System.Threading.Timer _timer = new Timer(ProcessTimer, null, 3000, Timeout.Infinite);
Mike_G
That works, but it's a bit verbose.
BCS
If this is declared as a variable then this probably won't work in Release mode; the timer will probably be garbage collected before it fires. You'll likely need to add a GC.KeepAlive(_timer) to the end of the method to work around this.
Greg Beech
And in keeping with Greg's statement, doing that sort of eliminates the simplicity of a single function call. This is much better encapsulated into a method once and reused.
Adam Robinson
Right, but as BCS said, he wants to test, not implement. If he is running a function that takes 5 seconds, and the timer fires in 3, Im willing to put $5 that GC will not come in to play.
Mike_G
Im also assuming the 5 second function call is not asynchronous
Mike_G
If you're testing, it's probably better if you have some pretty rock-solid confidence in the behavior of your TEST function, given that it's designed to be your "control". Betting on the .NET GC behavior is never wise.
Adam Robinson
Am I making a couple of assumptions? Sure, Im assuming the sync function really takes 5 seconds, and the timer function is as simplistic as BCS indicated. But given the information and examples provided, i cant imagine a scenario in which 5 seconds is shorter than 3 ;-)
Mike_G
@Mike_G - It looks like you don't quite understand some facets of GC. Firstly gen0 typically runs around 10x/second so yes it will come into play in a 3 second window. Secondly, in release mode, variables are eligible for collection immediately as they go out of scope (in this case, the line after the timer is declared). So there is a very real possibility the timer would be collected before it ever gets a chance to fire without a GC.KeepAlive after the end of the function that takes 5 seconds to run.
Greg Beech
+1  A: 
public static void RunAfter(int millisecondTimeout, 
    System.Threading.ThreadStart method) 
{ 
    System.Threading.Thread t = new System.Threading.Thread(() => 
    { 
        System.Threading.Thread.Sleep(millisecondTimeout); 

        method(); 
    }); 

    t.Start(); 
}

You could then do

RunAfter(3000, () => z = 5;);
Adam Robinson
I was kinda hoping for a standard function call
BCS
That's what you're getting here. There is no built-in function for doing this. This gives you a reuseable function that accomplishes what you want.
Adam Robinson
A: 

You could also use a WaitHandle to wait until a timeout occurs in a backgroundworker.

ManualResetEvent objResetEvent = new ManualResetEvent();
objResetEvent.WaitOne(timeout, ...);
Karol Deland
That doesn't give you a parallel thread; it just blocks your main thread.
Greg Beech
I forgot to indicate the use of the backgroundworker
Karol Deland