我在 .Net Framework 4.8 中使用了以下代码多年,用于在启动时显示启动屏幕:
Thread newWindowThread = new Thread(new ThreadStart(() =>
{
WpfSplashScreen splash = new WpfSplashScreen();//Get stuck here!
splash.Show();
Thread.Sleep(3000);
splash.Close();
}));
newWindowThread.SetApartmentState(ApartmentState.STA);
newWindowThread.IsBackground = true;
newWindowThread.Start();
//Loading some things...
Thread.Sleep(4000);
但是在将我的项目迁移到 .Net 8 后,它像以前一样停止工作。现在,创建用于显示 SplashScreen 的新线程卡在对话框初始化中,并且仅在主线程完成后才继续,这导致我的 SplashScreen 仅在所有加载完成后才打开。
在调试时,如果我进入“WpfSplashScreen()”,我可以看到线程在“InitializeComponent()”方法处停止。
我不想将我的 SlpashScreen 更改为另一个组件,这不是这里的想法,出于不同的原因,我在程序的许多部分使用相同的方法在自己的线程上打开其他对话框(例如进度条)窗口)并且所有案例在迁移后都有相同的问题。 SplashScreen 只是我关于这个问题的最简单的例子。所以我真的需要知道如何使 Wpf 对话框初始化不挂起 .Net 8 中的单独线程。
有什么想法吗?
虽然你的方法有效,但我仍然不建议这样做。一般来说,我会在极端必要的情况下(当不可能这样做时)保留显式创建线程。 这同样适用于所有 UI 元素。您应该仅在主应用程序线程中创建和使用它们。
因此,我建议您将您的代码替换为我在下面建议的代码。而且最好不仅要替换 Core/Net 应用程序中的代码,还要替换 Framework 中的代码。
{
WpfSplashScreen splash = new WpfSplashScreen();
splash.Loaded += async delegate
{
await Task.Delay(3000);
splash.Close();
};
splash.Show();
}
既然你经常使用这样的显示,你可以创建一个扩展方法并使用它:
public static class WindowHelper
{
public static void Show(this Window window, int delayClose)
{
window.Loaded += async delegate
{
await Task.Delay(3000);
window.Close();
};
window.Show();
}
}
{
new WpfSplashScreen().Show(3000);
}