背景:
我创建了一个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) {
}
}
答案 0 :(得分:2)
这是一种竞争条件,因为线程已经创建并声明但尚未创建SplashScreen。
换句话说,在创建之前,您正试图关闭启动画面。
您可以使用EventWaitHandle确保已创建SplashScreen,或者至少等待它不为空。
另一个选择是发出应关闭的屏幕信号并让他处理结束逻辑。