【问题标题】:Best way to use Thread in a complex/single window WPF application在复杂/单窗口 WPF 应用程序中使用 Thread 的最佳方式
【发布时间】:2012-07-09 11:40:00
【问题描述】:

我想知道改进我的 WPF 应用程序的最佳解决方案是什么。

我知道 WPF 会强制您在创建 UI 的线程上完成所有 UI 工作。这对我来说是个大问题,因为我的 UI 非常大,而且我只有 1 个窗口,所以我不能每个窗口拆分 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...

我在不同的网站上找到了他们谈论这个的地方......但没有回答我的问题:

Running WPF Application with Multiple UI Threads

MSDN

Working With The WPF Dispatcher

【问题讨论】:

  • 我在某处读到 UI 对象可以在不同的线程上创建。我需要找出答案。否则我认为 Kent 关于虚拟化的建议值得一看。
  • 1.5GB.. Top3 内存消耗对象类型是什么? (需要内存分析)。
  • 看看我的question。有一些很好的提示可以提高 UI 的响应能力。
  • 速度更快的机器,配备游戏级显卡。
  • 但是所有的工作都是由 CPU 完成的,显卡什么也不做,是的,我是 tier 2....

标签: c# .net wpf multithreading performance


【解决方案1】:

所以我对此进行了一些搜索。一个应用程序可以在不同的线程中创建不同的窗口或页面:一段代码取自here

  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 中的所有控件必须属于同一个线程。

【讨论】:

    【解决方案2】:

    听起来您最需要使用虚拟化技术。用户在任何时候都只能看到虚拟工作空间的一小部分,因此您应该只刷新那部分。

    除此之外,您是否进行了简介?究竟是什么与你的 CPU 挂钩?

    【讨论】:

    • 用户在缩小时可以同时看到所有部分。是的,我已经分析过了,渲染过程占用了主要的 CPU 工作
    • 为什么不能将缩放逻辑推送到服务器? IE。客户端只接收窗口大小的图像。客户端向服务器请求具有指定缩放级别和缩放点的该大小的图像。因此,当用户四处走动时,您只是向服务器请求一个较小的图像。
    • 它不仅仅是一个图像......我们的控件需要在我缩放或平移时工作,而正在消耗 CPU 的是它渲染给定图像时......
    【解决方案3】:

    我会“伪造”这些控件,并在缩放时将它们绘制到背景中。您甚至可以绘制看起来像控件的小图像。当使用较小(缩放)的背景时,您可以加快缩放速度。然后准备好后,我无法想象需要同时使用 2k 个控件,因此只能重新绘制或添加可以看到/操作的控件。计算每个控件的 x,y 并检查它们是否存在于 viewrectangle 中并绘制它们,比绘制它们要快得多。

    大部分壮观的图形都是通过这些技巧完成的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-10-07
      • 1970-01-01
      • 2011-01-07
      • 2013-03-15
      • 1970-01-01
      • 2018-04-14
      • 1970-01-01
      相关资源
      最近更新 更多