正在从子线程关闭父窗体

本文关键字:窗体 线程 | 更新日期: 2023-09-27 17:58:48

我对这个问题已经有一段时间了,尽管我在寻找解决方案,但我并不完全理解实现(已经研究了关于堆栈溢出的几个答案)

我的程序在打开时加载一个启动页,在此期间检查数据库连接。如果存在连接,启动页将关闭,主窗体将加载,否则它将提供一条错误消息,然后完全关闭。

public partial class StartupSplash : Form
{
    ThreadStart th;
    Thread thread;
    public StartupSplash()
    {
        InitializeComponent();
        th = new ThreadStart(DbAvaliable);
        thread = new Thread(th);
        thread.Start();
    }
    private void DbAvaliable()
    {
        Boolean result = false;
        using (var connectiontest = new SqlConnection("myConnString"))
            try
            {
                connectiontest.Open();
                result = true;
            }
            catch (Exception ex)
            {
                result = false;
            }
        if (result)
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new MainWindow());
        }
        else
        {
            MessageBox.Show("Unable to establish database connection. Please check your data connection and try again.");
        }
    }
}

我知道由于跨线程问题,我不能简单地调用this.Close()。我读过一些关于调用方法的文章,但我不太清楚如何实现上面的结果。

最初,我尝试使用表单加载/显示事件而不是备用线程,但表单上的图像未能加载,直到消息框显示错误(而不是显示,然后运行连接检查)

正在从子线程关闭父窗体

您能设置一个事件,用数据库检查的结果在Form2上激发吗?订阅Form1上的活动,并在条件允许的情况下通知其关闭。

不确定它是否有效,但类似于:

public Form2 : Form
{
    public delegate void DbCheckHandler(object sender, DbEventArgs e);
    public event DbCheckHandler DbCheckComplete;
    //check the db
    DbCheckComplete(this, new DbEventArgs { ShouldClose = true; });
}
public Form1 : Form
{
    Form2 form2 = new Form2();
    form2.DbCheckComplete += new DbCheckHandler(CheckDbResult);
    form2.Show();
    private void CheckDbResult(object sender, DbEventArgs e)
    {
        if(e.ShouldClose)
        {
            this.Close();
        }
    }
}

在Hans Passant之前发布的答案(这里和这里)的帮助下,我的解决方案如下:

static class Program
{
    /// <summary>
    /// The main entry point for the application.
    /// </summary>
    [STAThread]
    static void Main(string[] args)
    {   
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        new MyApp().Run(args);
    }
class MyApp : WindowsFormsApplicationBase
{
    protected override void OnCreateSplashScreen()
    {
        this.SplashScreen = new StartupSplash();
    }
    protected override void OnCreateMainForm()
    {
        Boolean result = false;
        using (var connectiontest = new SqlConnection("myConnectionString"))
            try
            {
                connectiontest.Open();
                result = true;
            }
            catch (Exception ex)
            {
                result = false;
            }
        // pause not needed while checking for db connection as that takes its own amount of time to complete.

        if (result)
        {
            System.Threading.Thread.Sleep(3000); //pause moved here to give the splash some time on screen if db connection available
            this.MainForm = new MainWindow();
        }
        else
        {
            MessageBox.Show("Unable to connect to the database");
            Environment.Exit(1); // shuts down the program if database connection not avaliable.
        }
    }

}