【问题标题】:NullReferenceException when closing a threaded form关闭线程表单时出现 NullReferenceException
【发布时间】:2011-08-10 07:39:34
【问题描述】:

上下文:

我创建了一个 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 上发生的频率更低......所以我有点困惑,除了我真的不明白在哪里它来自:

NullReferenceExceptionformSplashScreen.Invoke(...Close...) 行上引发,但 formSplashScreen 已正确初始化(我在调试时检查了它)。
我不确定这是来自线程还是来自其他点......

可能的解决方案:

我可能会用下面这样的东西来包围导致问题的线,但这只会绕过问题,我宁愿理解它并正确解决它。

while (splashScreenThread != null) {
    try {
        formSplashScreen.Invoke(new MethodInvoker(delegate {
            formSplashScreen.Close();
            formSplashScreen.Dispose();
        }));
        splashScreenThread = null;
    } catch (Exception e) {

    }
}

【问题讨论】:

  • 听起来像是竞争条件.. 尝试将此代码移动到 ShowSplashScreen 方法中。

标签: c# multithreading exception


【解决方案1】:

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

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

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

另一种选择是向屏幕发出信号,它应该关闭并让他处理关闭逻辑。

【讨论】:

猜你喜欢
  • 1970-01-01
  • 2013-11-06
  • 2012-07-26
  • 1970-01-01
  • 2021-02-22
  • 1970-01-01
  • 1970-01-01
  • 2016-10-28
  • 2018-03-25
相关资源
最近更新 更多