C# 同时运行两个 winform 窗口

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/15300887/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-10 16:22:37  来源:igfitidea点击:

Run two winform windows simultaneously

c#multithreadingwinforms

提问by RJB

I have two C# winform (.NET 4.0) forms that each run separate but similar automated tasks continuously. Separate in that they are distinct processes/workflows, but similar enough in how they operate to share the same resources (methods, data models, assemblies, etc) in the project.

我有两个 C# winform (.NET 4.0) 表单,每个表单都连续运行独立但相似的自动化任务。分开是因为它们是不同的过程/工作流,但它们在如何操作以共享项目中的相同资源(方法、数据模型、程序集等)方面足够相似。

Both forms are complete, but now I'm not sure how to run the program so that each window opens on launch and runs independently. The program will be "always-on" when deployed.

两种形式都已完成,但现在我不确定如何运行该程序,以便每个窗口在启动时打开并独立运行。该程序在部署时将“永远在线”。

This might seem a little basic, but most of my development experience has been web applications. Threading/etc is still a little foreign to me. I've researched but most of the answers I've found relate to user interaction and sequential use cases -- this will just be one system continuously running two distinct processes, which will need to interact with the world independently.

这可能看起来有点基础,但我的大部分开发经验都是 Web 应用程序。线程/等对我来说仍然有点陌生。我已经研究过,但我发现的大多数答案都与用户交互和顺序用例有关——这只是一个系统,连续运行两个不同的进程,它们需要独立地与世界交互。

Potential solutions I've found might involve multi-threading, or maybe some kind of MDI, or a few folks have suggested the DockPanelSuite (although being in a super-corporate environment, downloading third party files is easier said than done).

我发现的潜在解决方案可能涉及多线程,或者某种 MDI,或者一些人建议使用 DockPanelSuite(尽管在超级企业环境中,下载第三方文件说起来容易做起来难)。

static class Program
{
    /// <summary>
    /// The main entry point for the application.
    /// </summary>
    [STAThread]
    static void Main()
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);

        // Rather than specifying frmOne or frmTwo,
        // load both winforms and keep them running.
        Application.Run(new frmOne());
    }
}

采纳答案by Servy

You can create a new ApplicationContextto represent multiple forms:

您可以创建一个 newApplicationContext来表示多个表单:

public class MultiFormContext : ApplicationContext
{
    private int openForms;
    public MultiFormContext(params Form[] forms)
    {
        openForms = forms.Length;

        foreach (var form in forms)
        {
            form.FormClosed += (s, args) =>
            {
                //When we have closed the last of the "starting" forms, 
                //end the program.
                if (Interlocked.Decrement(ref openForms) == 0)
                    ExitThread();
            };

            form.Show();
        }
    }
}

Using that you can now write:

使用它,您现在可以编写:

Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new MultiFormContext(new Form1(), new Form2()));

回答by Paul Sasik

If you really need two windows/forms to run on two separate UI threads, you could do something like this:

如果你真的需要两个窗口/窗体在两个单独的 UI 线程上运行,你可以这样做:

static class Program
{
    [STAThread]
    static void Main()
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);

        var thread = new Thread(ThreadStart);
        // allow UI with ApartmentState.STA though [STAThread] above should give that to you
        thread.TrySetApartmentState(ApartmentState.STA); 
        thread.Start(); 

        Application.Run(new frmOne());
    }

    private static void ThreadStart()
    {
        Application.Run(new frmTwo()); // <-- other form started on its own UI thread
    }
}

回答by bas

Assumption

假设

You do not needthe two different processes, you are only using the 2 processes because you want to have the two different forms and want to be able to keep the application running until both forms are exited.

不需要这两个不同的进程,您只使用 2 个进程,因为您希望拥有两种不同的表单,并且希望能够让应用程序一直运行,直到退出这两个表单。

Another solution

另一种解决方案

Rely on the Form.Closedevent mechanism. You can add an eventhandler which allows you to specify what to do when a form closes. E.g. exit the application when bothforms are closed.

依靠Form.Closed事件机制。您可以添加一个事件处理程序,它允许您指定表单关闭时要执行的操作。例如,当两个表单都关闭时退出应用程序。

In terms of some code

在一些代码方面

    public Form1()
    {
        InitializeComponent();

        _form2 = new Form2();
        _form2.Show(this);

        this.Closed += Form1Closed;
        _form2.Closed += Form2Closed;
    }

    protected override void OnFormClosing(FormClosingEventArgs e)
    {
        e.Cancel = true;
        Hide();
        Form1Closed(this, new EventArgs());
        base.OnFormClosing(e);
    }

    private void Form1Closed(object sender, EventArgs eventArgs)
    {
        form1IsClosed = true;

        TryExitApplication();
    }

    private void Form2Closed(object sender, EventArgs eventArgs)
    {
        _form2IsClosed = true;

        TryExitApplication();
    }

    private void TryExitApplication()
    {
        if (form1IsClosed && _form2IsClosed)
        {
            Dispose();
            Application.Exit();
        }
    }

Note that this should be refactored to make it a better solution.

请注意,这应该重构以使其成为更好的解决方案。



UPDATE

更新

The comments provided by Servy made my revise this "supposed to be simple solution", which pointed out that his solution is way better then this solution. Since I am supported to leave the answer I will use this answer I will also address the issues that start arising when going for this solution:

Servy 提供的评论使我修改了这个“应该是简单的解决方案”,指出他的解决方案比这个解决方案更好。由于我支持留下答案,因此我将使用此答案,我还将解决在寻求此解决方案时开始出现的问题:

  • cancelling close events
  • rerouting from one event to another
  • force calling Dispose.
  • as Servy pointed out: maintenance unfriendly (state to check which form is closed)
  • 取消关闭事件
  • 从一个事件重新路由到另一个事件
  • 强制调用Dispose
  • 正如 Servy 指出的那样:维护不友好(状态检查哪个表单已关闭)