【问题标题】:Application.Run(Form) vs. Form.Show()?Application.Run(Form) 与 Form.Show()?
【发布时间】:2011-07-09 04:31:37
【问题描述】:

假设在主 GUI 线程上发生了很多事情(数据流入、用户操作等)。假设我们想创建一个表单并显示它。

如果我们使用Application.Run(Form) 而不是Form.Show(),会不会有性能提升?有一个更好的方法吗?请解释为什么或为什么不。

【问题讨论】:

  • 它会炸毁你的程序,每个线程只允许一个消息循环。某种提升,它可以更快地结束程序。消息循环永远不应该在关键路径上,它是在人工时间运行的。测量。

标签: c# winforms multithreading


【解决方案1】:

如果您指的是不是您应用的主要形式的东西,那么答案是否定的。 Application.Run() 初始化主消息循环并且应该在应用程序启动时只调用一次。应用生命周期内显示的所有其他表单应为 Form.Show 或等效形式。

您可以从另一个线程调用Application.Run,但是您将有两个 UI 线程无论如何您都需要同步。你不能只是传递东西而不确保你不会陷入争用情况。

【讨论】:

    【解决方案2】:

    除非你知道它的作用,否则不要使用Application.Run()。而且,一旦您知道它的作用,您就会知道为什么不应该在程序开始时使用它。

    Application.Run 启动消息泵。这是任何 GUI 程序的核心,也是使窗口能够接收消息、触发事件和执行操作的原因。你不能有两个消息泵,因为这没有任何意义。

    (是的,我知道你可以拥有两个消息泵,但你为什么想要?拥有 一个泵已经够难了!)

    至于您的 real 问题(我如何不在我的 GUI 线程上做事),这有点复杂。最简单的答案是“使用线程”。由于我不知道你的具体情况,我只能给出一些一般性的建议:

    1. 不要尝试从其他线程操作控件。充其量是行不通的。在最坏的情况下,它会让你的房子着火(好吧,也许没那么糟糕。但是,不要这样做。)。相反,您需要Invoke 方法。下面将提供一个示例。

    2. 不要在您的 GUI 线程上运行长时间运行的进程。简短的事情是可以的,但任何可能需要超过半秒的事情可能最好卸载到另一个线程。

    3. 使用事件从您的 Worker 线程传回您的 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)。完成后,它会Invokes WorkFinished 函数,该函数会显示结果(否则会清除状态)。

    【讨论】:

    • 顺便说一句,我们应该在Application.Run(myForm) 行之后处理myForm 吗?正如 SolarLint 建议的那样
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多