【问题标题】:Closing a 'form' from another 'form'从另一个“表单”关闭一个“表单”
【发布时间】:2011-09-10 22:03:47
【问题描述】:

我开发了一个应用程序,我在其中使用 Windows 窗体作为启动屏幕。显示启动画面后,我创建了一个新线程来触发新表单。现在我想在我的表单显示后关闭启动画面。

我用谷歌搜索了我的查询,进行了很多讨论,但找不到我想要的。

请指导一下。

谢谢。

【问题讨论】:

标签: c# winforms


【解决方案1】:

只要您对第一个表单有一些引用,您就可以在另一个表单上调用Close() 方法。因此,当您创建第二个表单时,请为其提供对启动画面的引用。然后将处理程序附加到 Shown 事件并在初始屏幕上调用 close。

为了解决跨线程问题,您需要创建一个名为 ThreadSafeClose 之类的方法,并将其定义如下。然后调用该方法而不是.Close()

public void ThreadSafeClose() {
        if(this.InvokeRequired) {
            this.Invoke(new MethodInvoker(this.Close));
        }
    }

【讨论】:

  • 表格在不同的线程上。您不能只从另一个线程调用控件的方法。您需要使用 Invoke() 从 spash 的线程中运行 Close()。
【解决方案2】:

为了关闭表单,您需要有一个指向此表单的链接。最简单的方法是向程序中的Program 对象添加一个新属性,该属性是静态的且随处可用。只需修改您的 Program.cs 文件以公开 Program 类并添加适当的引用:

public static class Program
{
    ///This is your splash screen
    public static Form1 MySplashScreen = new Form1();

    static void Main()
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        /// This is how you run your main form
        Application.Run(MySplashScreen);
    }
}

然后在您的表单中,您可以使用以下语法轻松关闭初始屏幕表单:

Program.MySplashScreen.Close();

编辑:在 WinForms 中只有一个 GUI 线程,所以只要您从另一个窗体中执行关闭它应该是安全的。如果您想从 GUI 生成的工作线程中关闭表单,请使用以下代码(这应该引用您的第二个表单):

this.Invoke((MethodInvoker)delegate {
            Program.MySplashScreen.Close();
});

【讨论】:

    【解决方案3】:

    通常您不需要新线程。但是一旦你有了它,你可以通过在两个线程之间共享一个布尔值(命名为 closeSplash)来实现它。

    在启动表单上放置一个计时器,以每秒检查 closeSplash 的值。当closeSplash为true时,调用Splash表单的Close()方法即可。

    如果您选择从另一个线程关闭启动画面,请参阅this

    【讨论】:

    • @Muhammad Ali Dildar 你是怎么解决的?任何答案是否提供了解决方案?如果是,请将该答案标记为解决方案。
    【解决方案4】:

    我有一个我使用的 hacky 方法 .. 可能不是最好的做法。 在闪屏表单中声明一个自身的静态实例。

    public static SplashForm splashInstance;
    

    然后在splashform的构造函数中你可以赋值“this”。

    SplashForm.splashInstance = this;
    

    您现在可以从应用内的任何位置调用 SplashForm.splashInstance.Close()。

    【讨论】:

    • 注意:直接从另一个线程调用 Close() 是无效的。你需要切换到splash的表单线程上下文来运行代码。
    • @Muhammad Ali Dildar 请看我上面的回答,有一个链接可能会有所帮助。我个人尽量避免将 UI 消息从一个线程发送到另一个线程。相反,请尝试使用一些共享成员/属性向其他线程发出信号,表明您希望 UI 执行某些操作。
    【解决方案5】:

    您确实需要一个单独的线程来在一段时间内显示“启动画面”。事实上,有更好的方法可以让你设计你的类,让这件事更容易完成。不在这里使用计时器或为此使用单独的线程不是正确的解决方案恕我直言。我建议你尝试做这样的事情:

    public class SplashScreen : Form
    {
        // add a timer to your form with desired interval to show
    
        protected override void OnShown(EventArgs e)
        {
            displayTimer.Start();
            base.OnShown(e);
        }
    
        private void displayTimer_Tick(object sender, EventArgs e)
        {
            this.Close();
        }
    }
    
    public class MainForm : Form
    {
        protected override void OnLoad(EventArgs e)
        {
            // splash screen will be shown before your main form tries to show itself
            using (var splash = new SplashScreen())
                splash.ShowDialog();
            base.OnLoad(e);
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-07-27
      • 1970-01-01
      • 2013-08-21
      • 2011-02-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多