C #, WPF, Automatically call Dispatcher.Invoke if necessary?

I have a program with a Geospace card built into it. Event processing for the card is processed in a separate thread so that the card responds (for example, events that fire when a card is clicked).

The problem I am facing is when the card fires the event, my program needs to update some things in it gui, and also call back to the card in order to handle the placement of images on the map.

I tried wrapping the entire event handler method in this.Dispatcher.Invoke, which returns me to the main UI thread. This works great for updating my GUI, but when I call back on the map, I am still in the UI thread, which may cause some problems on the map.

Basically, to do this, I will have to run dispatcher.invoke every time I want to change a control on my gui. Is there a way I can automatically do this without wrapping every call in dispatcher.invoke? I hope all this makes sense.

Here is a sample code for the event I'm talking about.

private void Map_OnMapClicked(object sender, MapClickedEventArgs e) { this.Dispatcher.Invoke(DispatcherPriority.Normal, (Action)(() => { // Do something to update my gui })); Map.DoSomethingInTheMap(); this.Dispatcher.Invoke(DispatcherPriority.Normal, (Action)(() => { // Do something to update my gui })); //etc etc etc } 
+6
c # wpf dispatcher
source share
2 answers

If you need to save each relevant operation in your own synchronization context, this is, unfortunately, the best approach. You will need to invoke the use of the Dispatcher whenever you update your GUI.

Here are some tips to ease this:

  • Try performing operations with the graphical interface. In addition to requiring less code (with less call calls) you will get better performance. Each call to Dispatcher.Invoke carries enough overhead because it sends a message to the dispatcher message queue that needs to be processed.

  • Consider using Dispatcher.BeginInvoke to avoid blocking if you really don't have to wait.

  • If you can use the parallel task library from .NET 4 (or backport to 3.5sp1 in the Rx Framework), you may need to rework this to use task instances synchronized with the GUI thread . By creating a TaskScheduler using the FromCurrentSynchronizationContext function, you can schedule tasks to run in the GUI more easily than calling Dispatcher Invoke. It can also give you some control over batch processing, as you can schedule them and block / wait as needed very easily.

+6
source share

You can use something like PostSharp or try to condense updates of your user interface to calls with one call, where you call once and do a lot, Or even such a template (these are Winforms, but the idea is the same):

 private void UpdateToolStripItemText(ToolStripItem toolStripItem, string text) { if (InvokeRequired) { Invoke(new UpdateToolStripItemTextDelegate(UpdateToolStripItemText), new object[] { toolStripItem, text }); } else { if (text != null) { toolStripItem.Text = text; } } } 
+2
source share

All Articles