C#,WPF,在需要时自动调用Dispatcher.Invoke? [英] C#, WPF, Automatically call Dispatcher.Invoke when needed?

查看:444
本文介绍了C#,WPF,在需要时自动调用Dispatcher.Invoke?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个程序,其中嵌入了Geospace地图。地图的事件处理是在单独的线程上处理的,以保持地图的响应性(例如,单击地图时会触发的事件)。

I have a program with a Geospace map embedded into it. The event handling for the map is handled on a separate thread to keep the map responsive (for example, the events that fire when the map is clicked).

问题我当地图触发事件时,我的程序需要更新它的gui中的某些内容,还需要回调到地图中以处理在地图上放置图片的情况。

The problem I am having is when the map fires an event, my program needs to update some things in it's gui, and also call back into the map to handle placing pictures on the map.

我尝试将整个事件处理程序方法包装在this.Dispatcher.Invoke中,这使我回到了主UI线程上。这对于更新我的GUI非常有用,但是当我回调到地图上时,我仍然在UI线程上,这可能会在地图上引起一些问题。

I tried wrapping the entire event handler method in this.Dispatcher.Invoke, which puts me back on the main UI thread. This works great for updating my GUI, but when i call back into the map, I'm still on the UI thread which can cause some problems in the map.

,为了使此工作正常进行,每次要更改gui控件时,我都必须运行dispatcher.invoke。有没有一种方法可以自动执行此操作而无需将每个调用都包装在dispatcher.invoke中?我希望这一切都说得通。

Basically, in order to make this work, I'm going to have to run dispatcher.invoke each time I want to change a control on my gui. Is there a way I can automatically do this without wrapping each call in dispatcher.invoke? I hope this all makes sense.

这里有一些我正在谈论的事件的示例代码。

Heres some example 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
    }


推荐答案

如果您需要将每个操作都保留在自己的同步上下文中,那么不幸的是,这是最好的方法。每当您更新GUI时,都需要使用Dispatcher进行调用。

If you need to keep each respective operation in its own synchronization context, this is unfortunately the best approach. You'll need to Invoke using the Dispatcher whenever you update your GUI.

以下有一些建议可以简化此操作:

Here are a couple of suggestions for making this easier:


  1. 尝试批处理GUI操作。除了需要更少的代码(通过更少的调用调用)之外,您还将获得更好的性能。每个Dispatcher.Invoke调用都会产生相当大的开销,因为它会将一条消息发布到必须处理的Dispatcher的消息队列中。

  1. Try to batch your GUI operations. In addition to requiring less code (via less invoke calls), you'll get better performance. Each Dispatcher.Invoke call carries a fair amount of overhead, since it posts a message into the Dispatcher's message queue which must be processed.

请考虑使用Dispatcher.BeginInvoke为避免阻塞,除非您确实需要等待。

Consider using Dispatcher.BeginInvoke to avoid blocking, unless you really need to wait.

如果您可以使用.NET 4中的任务并行库(或反向移植到3.5sp1中, Rx Framework),您可能需要考虑对其进行改编以使用任务实例已同步到GUI线程。通过使用FromCurrentSynchronizationContext创建TaskScheduler,您可以安排任务比在Dispatcher Invoke调用上更容易在GUI上运行。这还可以使您对批处理有所控制,因为您可以安排它们,并根据需要轻松地阻止/等待。

If you can use the Task Parallel Library from .NET 4 (or the backport to 3.5sp1 in the Rx Framework), you might want to consider reworking this to use Task instances synchronized to the GUI thread. By creating a TaskScheduler using FromCurrentSynchronizationContext, you can schedule tasks to run on the GUI easier than the Dispatcher Invoke calls. This also can give you some control over batching, since you can schedule them, and block/wait as needed, very easily.

这篇关于C#,WPF,在需要时自动调用Dispatcher.Invoke?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆