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

时间:2012-07-09 11:40:01

标签: c# .net wpf multithreading performance

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

我知道WPF会强制您在创建UI的线程上执行所有UI工作。这对我来说是一个主要问题,因为我的UI非常庞大而且我只有一个窗口,所以我不能在每个窗口中拆分1个线程。

当我进行平移和缩放时,每次都需要刷新所有内容,我的一个CPU达到100%的使用率,直到完成所有操作。

所以我会尝试解释我在申请中的内容:

  • 1个窗口(屏幕大小)
  • 虚拟面板,12000像素X 12000像素(我可以平移和缩放)
  • 约2000个控件(按钮,开关和其他一些复杂控件)
  • 在我的控件后面,我的背景有一个很大的位图,但是我将背景分成100个较小的位图(我堆叠了12个像素,12k像素的12位像素使我的应用程序崩溃)
  • 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

3 个答案:

答案 0 :(得分:2)

所以我对此进行了一些搜索。一个应用程序可以在不同的线程中创建不同的窗口或页面:从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();
  }

这是个好消息。但是在你的情况下并不真正适用,因为你有一个Window,我试过这个并不是真的有效:

     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 :(得分:1)

听起来你需要使用虚拟化而不是其他任何东西。用户只能随时看到虚拟工作区的一小部分,因此您应该只刷新该部分。

除此之外,您有什么想法吗?什么是与你的CPU挂钩?

答案 2 :(得分:0)

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

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