多线程上的 WPF UI?

Kel*_*lly 4 c# wpf multithreading

我有一个大型 WPF MVVM 应用程序(目前有超过 100 个窗口,并且还在不断增长)。尽管我尝试在后台线程上尽我所能,但总有一天结果必须发送回 UI 线程才能显示。当有多个窗口同时执行此操作时,可能会影响性能。

过去我曾尝试在单独的 UI 线程上运行每个窗口,但遇到了很多线程问题,我不得不恢复到 WPF 每个应用程序仅 1 个 UI 线程的默认模型。

我知道随着 Windows 10 的推出,许多用户将在不同的桌面上打开更多窗口,从而使情况变得更糟。

有人知道如何让多个 UI 线程在 WPF 中正常工作吗?或者有任何我可以调查的信息来帮助我的应用程序沿着这条路走得更远吗?

我过去尝试过的方法是做类似的事情:

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();
  }
Run Code Online (Sandbox Code Playgroud)

那是大约两年前的事了,不幸的是,我无法回忆起使用它时遇到的所有问题。

还有别的办法吗?有没有人使用这种方法或其他方法获得具有多个窗口的应用程序可以正常工作?

Pet*_*iho 6

一般来说,它“有效”。您要做的主要事情是将线程设置为 STA(如您的示例中所示)。但是,通过在不同的线程中运行某些 UI,您几乎没有什么收获,甚至什么也得不到。每个线程仍然可能被长时间运行的任务阻塞,因此您仍然需要在另一个线程中执行这些任务,并且仍然存在跨线程问题,需要某种形式的封送回 UI 线程(例如Dispatcher.Invoke())。

此外,对于多个 UI 线程,现在您不仅必须跟踪哪个 UI 线程与哪个 UI 对象相关(因为它们仍然只能与拥有它们的线程一起使用),而且还会遇到更多 UI 问题对象彼此交互,因为不同线程拥有的对象是互斥的。每个都只能在它所属的线程中访问,因此让它们一起工作的唯一方法是创建某种代理系统来在线程之间来回传递数据和事件。

基本上,为 UI 创建多个线程从来都不是、现在也不是一个好主意。

幸运的是,从 .NET 4.5 和 C# 5.0 开始,框架和语言功能大大简化了后台操作的处理以及将信息封送回 UI 线程的过程。使用async/功能,您可以使用类或某些类方法(通常名称以单词结尾)await等框架功能启动异步操作,在操作期间使 UI 线程畅通无阻,并且可以轻松编写代码来处理任何事情工作必须在操作结束时完成。Task<T>Async

还有一个Progress<T>类,它IProgress<T>以方便处理UI进度更新的方式实现接口,即在UI线程上调用回调(当然Progress<T>,只要您在UI线程中创建实例)。

因此,走 .NET 和 C# 鼓励您走的路,避免走困难的路。将所有 UI 保持在一个线程中,并使用提供的工具解决出现的任何问题,而不是尝试与 API 对抗。:)