Application.Run(Form)和Form.Show()的区别是什么?

8
假设主GUI线程上有很多事情正在发生(数据流入,用户操作等)。假设我们想创建一个表单并显示它。
如果我们使用Application.Run(Form)而不是Form.Show(),是否可以提高性能?是否有更好的方法来实现这一点?请解释原因。

3
它会炸掉你的程序,每个线程只允许一个消息循环。某种提升,它可以更快地结束程序。消息循环不应该在关键路径上运行,它以人类时间运行。请测量。 - Hans Passant
2个回答

15
除非你知道Application.Run()的作用,否则不要使用它。一旦你知道它的作用,你就会知道为什么只有在程序开头才能使用它。 Application.Run启动一个消息泵。这是任何GUI程序的核心,它使窗口接收消息,从而触发事件并执行操作。您不能有两个消息泵,因为这没有任何意义。
(是的,我知道你可以有两个消息泵,但你为什么想要呢?即使只有一个泵也很难!)
至于你的真正问题(如何在GUI线程上不执行操作),这有点复杂。最简单的答案是“使用线程”。由于我不知道你的具体情况,所以我只能给出一些一般性建议:
1.不要尝试从其他线程操作控件。最好的情况下,它不起作用。在最坏的情况下,它会引起灾难(好吧,也许没有那么严重。但是,不要这样做)。相反,你需要Invoke方法。下面将提供一个示例。
2.不要在GUI线程上运行长时间运行的进程。短暂的事情还好,但任何可能超过半秒钟的东西最好转移到另一个线程。
3.使用事件从你的工作线程向GUI线程通信。
以下是如何运行工作线程的示例:
delegate void VoidDelegate();

List<int> results;
bool cancelWork = false;

void DoWork() {
    int calc;
    results = new List<int>();

    for(int i = int.MinValue ; i < int.MaxValue; i+=10) {
        if(cancelWork) break;
        results.Add(i);
    }

    this.Invoke(new VoidDelegate(WorkFinished));
}

void Button1_Click(object sender, EventArgs e) {
    button1.Enabled = false;
    button2.Enabled = true;
    cancelWork = false;
    Thread t = new Thread(DoWork);
    t.Start();
}

void Button2_Click(object sender, EventArgs e) {
    button2.Enabled = false;
    cancelWork = true;
}

void WorkFinished() {
    button1.Enabled = true;
    button2.Enabled = false;
    textBox1.Text = results.Count.ToString();
}

显然,这只是一个刻意编造的例子,但它能够达到我的目的。
这个假设的表单包含两个按钮:button1(“运行”)和button2(“取消”),以及一个文本框textbox1。在开始时,button2应该是禁用状态(Enabled = false)。
当工作线程正在运行时,用户可以与任何其他控件交互,包括“取消”按钮(在我的示例中为button2)。一旦完成,它会Invoke WorkFinished函数,该函数显示结果(并清除状态)。

顺便问一下,我们应该在Application.Run(myForm)行之后处理myForm吗?就像SolarLint建议的那样。 - Yousha Aleayoub

6
如果您正在引用的是与您的应用程序主窗体不同的内容,则答案是否定的。 Application.Run() 初始化主消息循环,并且在应用程序启动时只应调用一次。在应用程序生命周期中显示的所有其他表单都应为Form.Show或等效形式。
您可以从另一个线程调用Application.Run,但是那么您将需要同步两个UI线程。您不能仅仅传递东西而不确保您不会进入争用情况。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接