我有一个大型 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();
}
这是大约 2 年前的事了,不幸的是,我已经记不起我在使用它时遇到的所有问题。
还有别的办法吗?有没有人使用这种或另一种方法获得了具有多个窗口的应用程序以正常工作?
最佳答案
一般来说,它“有效”。您要做的主要事情是将线程设置为 STA(如您的示例所示)。但是,通过在不同的线程中运行某些 UI,您将获得很少或一无所获。每个线程仍可能被长时间运行的任务阻塞,因此您仍然需要在另一个线程中执行这些任务,并且您仍然会遇到跨线程问题,需要某种形式的编码返回到 UI 线程(例如 Dispatcher.Invoke()
)。
此外,有了多个 UI 线程,现在您不仅需要跟踪哪个 UI 线程与哪个 UI 对象一起使用(因为它们仍然只能与拥有它们的线程一起使用),您将拥有更多UI 对象相互交互的问题,因为不同线程拥有的对象是相互排斥的。每个都只能在它所属的线程中访问,因此让它们一起工作的唯一方法是创建某种代理系统来在线程之间来回传递数据和事件。
基本上,为 UI 创建多个线程从来都不是,现在仍然不是一个好主意。
幸运的是,从 .NET 4.5 和 C# 5.0 开始,框架和语言功能大大简化了后台操作的处理以及将信息编码回 UI 线程。随着async
/await
功能,您可以使用框架功能启动异步操作,例如 Task<T>
类或某些类方法(通常名称以单词 Async
结尾),让 UI 线程在操作期间畅通无阻,并且轻松编写代码来处理操作结束时必须完成的任何工作。
还有 Progress<T>
类,它实现了 IProgress<T>
界面以一种方便处理 UI 进度更新的方式,即在 UI 线程上调用回调(当然,只要您在 UI 线程中创建 Progress<T>
实例)。
因此,走 .NET 和 C# 鼓励您走的路,避免走困难的路。将所有 UI 保持在一个线程中,并使用提供的工具解决出现的任何问题,而不是试图与 API 作对。 :)
关于c# - 多线程上的 WPF UI?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28313395/