Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Delayed Dispatch Invoke?

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 :)

like image 820
Homde Avatar asked Sep 18 '10 08:09

Homde


People also ask

What does Dispatcher invoke?

Invoke(Action, DispatcherPriority) Executes the specified Action synchronously at the specified priority on the thread the Dispatcher is associated with. Invoke(Action) Executes the specified Action synchronously on the thread the Dispatcher is associated with.

Is dispatcher invoke synchronous?

Invoke is synchronous and BeginInvoke is asynchronous. The operation is added to the event queue of the Dispatcher at the specified DispatcherPriority. If BeginInvoke is called on a Dispatcher that has shut down, the status property of the returned DispatcherOperation is set to Aborted.

What is Dispatcher c#?

The Dispatcher maintains a prioritized queue of work items for a specific thread. When a Dispatcher is created on a thread, it becomes the only Dispatcher that can be associated with the thread, even if the Dispatcher is shut down.


2 Answers

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.

like image 116
Jon Skeet Avatar answered Sep 21 '22 20:09

Jon Skeet


A .NET 4.5 way:

    public async void MyMethod()
    {
        await Task.Delay(20); 
        await Dispatcher.BeginInvoke((Action)DoStuff);
    }
like image 40
Anthony Hayward Avatar answered Sep 22 '22 20:09

Anthony Hayward