views:

55

answers:

2

In WPF due to the intricacies on how the interface is updated I sometimes have to perform actions after a short delay.

Currently I'm doing this simply by:

        var dt = new DispatcherTimer(DispatcherPriority.Send);
        dt.Tick += (s, e) =>
        {
            dt.Stop();
            //DoStuff
        };
        dt.Interval = TimeSpan.FromMilliseconds(200);
        dt.Start();

But it's both a bit ugly and perhaps too much overhead to create a new timer each time (?) What's the best from a performance standpoint to do it, ie execute most promptly? And what's good way to rewrite the above code into something like:

        this.Dispatcher.BeginInvoke(new Action(delegate()
        {
            //DoStuff
        }), DispatcherPriority.Send,TimeSpan.FromMilliseconds(200));

Where Timespan is the delay, Thanks for any input :)

+3  A: 

I wouldn't assume that the DispatcherTimer is heavy-weight... why not just write an extension method on Dispatcher which allows you to use the syntax you want, and uses a DispatcherTimer in the background? I would personally call it DelayInvoke rather than BeginInvoke though... and I'd also fix it to always use Action rather than an arbitrary delegate... that will make it easier to use lambda expressions:

Dispatcher.DelayInvoke(TimeSpan.FromMilliseconds(200), () => { ... 
});

(I tend to find it's more readable if anonymous functions are used as the final argument in a method call, but that's just a personal preference.)

Given that you'll quite possibly want to use milliseconds most of the time, you could have another helper method too:

Dispatcher.DelayInvokeMillis(200, () => { ... 
});

Another alternative to try is merely to use the existing BeginInvoke method but with a very low priority, so your delegate will only be invoked after everything else has finished. Without knowing the details of your situation, it's hard to know whether that'll work or not - but it's worth trying.

Jon Skeet
An extension method would be very nice, but wouldn't that mean I would first have to do a begininvoke on the dispatcher to be on the right thread and then set up the timer, which is a little more overhead than just having the timer? Might not be an issue though...
MattiasK
@MattiasK: Why would it need to do that? It wouldn't *really* need to interact with the dispatcher at all... that would just be for the sense of consistency. Admittedly I don't know what happens if you create a DispatcherTimer from a different thread... but if it works when done directly, it would work from an extension method without any extra problems.
Jon Skeet
@MattiasK: I've just checked, and you can tell the DispatcherTimer constructor which Dispatcher it should run on - so you'd use that overload from the extension method, and specify the Dispatcher which had been passed to the method.
Jon Skeet
Thanks, I'll give it a try
MattiasK
A: 

You might be able to use the Paul Stowell's DelayBinding class from here: http://www.paulstovell.com/wpf-delaybinding.

With this can can bind to a DependencyProperty on a class that can execute the action when the property changes. The binding will manage the delay. Might be particularly nice if you have a MVVM-type design.

Govert