我有一个嵌入了Geospace map 的程序。针对 map 的事件处理在单独的线程上进行处理,以保持 map 响应(例如,单击 map 时触发的事件)。

我遇到的问题是,本地图触发事件时,我的程序需要更新gui中的某些内容,并且还需要回调 map 以处理在 map 上放置图片的问题。

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

基本上,为了完成这项工作,每次要更改GUI的控件时,我都必须运行dispatcher.invoke。有没有一种方法可以自动执行此操作而无需将每个调用都包装在dispatcher.invoke中?我希望这一切都是有道理的。

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

    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进行调用。

这里有一些建议可以使此操作变得更容易:

  • 尝试批处理GUI操作。除了需要更少的代码(通过更少的调用调用)之外,您还将获得更好的性能。每个Dispatcher.Invoke调用都会带来相当大的开销,因为它会将消息发布到必须处理的Dispatcher的消息队列中。
  • 考虑使用Dispatcher.BeginInvoke以避免阻塞,除非您确实需要等待。
  • 如果可以使用.NET 4中的任务并行库(或Rx Framework中向3.5sp1的反向移植),则可能需要考虑对其进行改编以使用Task instances synchronized to the GUI thread。通过使用FromCurrentSynchronizationContext创建TaskScheduler,您可以安排任务比在Dispatcher Invoke调用上更容易在GUI上运行。这还可以使您对批处理有所控制,因为您可以计划它们,并根据需要轻松地阻止/等待。
  • 关于c# - C#,WPF,在需要时自动调用Dispatcher.Invoke?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/2211016/

    10-13 06:31