关闭线程窗体时的NullReferenceException
本文关键字:NullReferenceException 窗体 线程 | 更新日期: 2023-09-27 18:04:55
上下文:
我创建了一个Windows窗体应用程序,它在启动前运行启动屏幕。快速地,这里是包含我的Program.cs
:
public static Thread splashScreenThread = null;
public static FormSplashScreen formSplashScreen;
[STAThread]
static void Main(string[] args) {
// Show splash screen
splashScreenThread = new Thread(new ThreadStart(ShowSplashScreen));
splashScreenThread.IsBackground = true;
splashScreenThread.Start();
// Load some components in background
LoadComponentsInBackground()
// Hide the splash screen
if (splashScreenThread != null) {
formSplashScreen.Invoke(new MethodInvoker(delegate {
formSplashScreen.Close();
formSplashScreen.Dispose();
}));
splashScreenThread = null;
}
// Start now the application
Application.Run();
}
private static void ShowSplashScreen() {
formSplashScreen = new FormSplashScreen();
formSplashScreen.ShowDialog();
}
问题:
我的问题并不是每次我启动应用程序时都发生,它似乎是随机的,在某些pc上更经常发生,而在其他pc上更少…所以我有点困惑,而且我真的不明白它是从哪里来的:
NullReferenceException
在formSplashScreen.Invoke(...Close...)
行上被抛出,但formSplashScreen
被正确初始化(我在调试时检查了它)。
我不确定这是来自线程还是来自另一个点…
可能的解决方案:
我也许可以用下面这样的东西把引起问题的行括起来,但这只是绕过问题,我宁愿理解它并正确解决它。
while (splashScreenThread != null) {
try {
formSplashScreen.Invoke(new MethodInvoker(delegate {
formSplashScreen.Close();
formSplashScreen.Dispose();
}));
splashScreenThread = null;
} catch (Exception e) {
}
}
这是一个竞态条件,因为线程已经创建并启动,但是SplashScreen还没有创建。
换句话说,你试图在启动屏幕创建之前关闭它。
你可以使用EventWaitHandle来确保SplashScreen已经被创建,或者至少等到它不为空。
另一个选择是向屏幕发出关闭的信号,让他处理关闭逻辑。