关闭线程表单时出现NullReferenceException

时间:2011-08-10 07:39:35

标签: c# multithreading exception

背景:

我创建了一个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) {

    }
}

1 个答案:

答案 0 :(得分:2)

这是一种竞争条件,因为线程已经创建并声明但尚未创建SplashScreen。

换句话说,在创建之前,您正试图关闭启动画面。

您可以使用EventWaitHandle确保已创建SplashScreen,或者至少等待它不为空。

另一个选择是发出应关闭的屏幕信号并让他处理结束逻辑。