在复杂/单个窗口WPF应用程序中使用线程的最佳方法

3
我想知道如何改进我的WPF应用程序,最好的解决方案是什么。
我知道WPF强制要求在创建UI的线程上完成所有UI工作。这对我来说是一个很大的问题,因为我的UI非常庞大,而我只有一个窗口,所以我无法为每个窗口分配1个线程。
当我进行平移和缩放时,每次都需要刷新所有内容,其中一个CPU使用率达到100%,直到所有内容都完成。
所以我会尝试解释一下我的应用程序:
- 1个窗口(屏幕大小) - 虚拟面板,12000像素X 12000像素(我在其中进行平移和缩放) - 约2000个控件(按钮、开关和其他一些复杂的控件) - 在我的控件后面,我有一个大的位图作为背景,但我将我的背景分成了大约100个更小的位图,然后堆叠起来(因为1个12k像素x 12k像素的位图会导致我的应用程序崩溃) - 10个虚拟显示器,连接到远程计算机(提供位图),并且每50毫秒刷新其内容 - .NET 4.0,多点触控应用程序

我的应用程序可以进行平移和缩放(不使用10个显示器),但由于控件数量太多,存在很多延迟,当我添加显示器时,延迟会翻倍...

我的应用程序大约占用1.5 GB的虚拟内存。

我尝试使用调度程序在需要时创建线程,但我找不到想要的内容... 他们到处都在谈论1个线程/窗口... 但我只有1个窗口,不知道该怎么办。

  • 我不能将其拆分为较小的窗口。
  • 我不能减少控件数量或刷新时间。
  • 我不能更改技术(WPF)

所以这是真正的问题:我在哪里可以创建新线程来帮助我的渲染时间?将工作分配给不同的CPU...

我找到了一些网站,他们谈论这个问题... 但没有回答我的问题:

使用多个UI线程运行WPF应用程序

MSDN

使用 WPF 调度程序


我在某处读到UI对象可以在不同的线程上创建。我需要找出来。否则,我认为肯特关于虚拟化的建议是值得考虑的。 - MBen
1
看看我的问题。那里有一些不错的提示可以提高你的用户界面的响应能力。 - Willem
更快的机器,配备游戏级别的显卡。 - paparazzo
但是所有的工作都是由CPU完成的,显卡什么也不做,是的我是二级支持。 - mlemay
我不确定XNA是什么,但如果它取代了WPF,我们不能这样做,我们需要继续使用WPF... - mlemay
显示剩余2条评论
3个回答

2

我稍微搜索了一下相关内容。一个应用程序可以在不同的线程中创建不同的窗口或页面: 代码片段来自于这里

  private void OnCreateNewWindow(
  object sender,
  RoutedEventArgs e)
  {
    Thread thread = new Thread(() =>
    {
      Window1 w = new Window1();
      w.Show();

      w.Closed += (sender2, e2) =>
      w.Dispatcher.InvokeShutdown();

      System.Windows.Threading.Dispatcher.Run();
    });

   thread.SetApartmentState(ApartmentState.STA);
   thread.Start();
  }

那么这是好消息。但在你的情况下,这并不适用,因为你只有一个窗口,而我尝试过这个方法,它并没有真正起作用:

     private void OnCreateNewWindow(object sender, RoutedEventArgs e)
     {
       SynchronizationContext syncContext = SynchronizationContext.Current;
       var btn = sender as Button;
       var st = btn.Parent as StackPanel;

       Thread thread = new Thread(() =>
         {
            Button button = new Button();
            syncContext.Post(delegate { st.Children.Add(button) ;}, null); //Exception here
         });

        thread.SetApartmentState(ApartmentState.STA);
        thread.Start();
     }

我尝试在不同的线程中创建一个单独的控件,这可以实现,但是当我尝试将其添加到stackPanel时,它会失败并显示InvalidOperationException错误。

我知道这并没有直接回答你的问题,但至少你知道所有在同一Window中的控件必须属于相同的线程。


1

听起来你需要更多地使用虚拟化技术。用户每次只能看到虚拟工作区的一小部分,因此你应该只刷新那一部分。

除此之外,你有进行过性能分析吗?到底是什么导致了CPU占用率过高?


当用户缩小视图时,他可以同时看到所有部件。是的,我已经进行了分析,渲染过程占用了大部分CPU工作。 - mlemay
为什么不能将缩放逻辑推到服务器端?即客户端只接收窗口大小的图像。客户端请求具有指定缩放级别和缩放点的该尺寸图像。因此,当用户移动时,您只需向服务器请求单个较小的图像。 - Kent Boogaart
不仅仅是一张图片...我们的控件需要在我缩放或平移时工作,而且杀死CPU的是它渲染给定的图片时... - mlemay

0

在缩放时,我会“伪造”这些控件并将它们绘制成背景。甚至可以绘制看起来像控件的小图像。使用较小(缩放)的背景可以加速缩放。然后,当准备好时,我无法想象需要同时使用2k个控件,因此只需重新绘制或添加可见/可操作的控件即可。计算每个控件的x,y位置,并检查它们是否出现在视图矩形中并进行绘制,比全部绘制要快得多。

大多数壮观的图形都是用这些技巧完成的。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接