同时运行两个winform窗口

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

两种forms都是完整的,但现在我不知道如何运行程序,以便每个窗口在启动时打开并独立运行。 部署后,该程序将“始终开启”。

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

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

static class Program { ///  /// The main entry point for the application. ///  [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()); } } 

您可以创建一个新的ApplicationContext来表示多个表单:

 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(); } } } 

使用它你现在可以写:

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

如果你真的需要两个窗口/表单在两个独立的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 } } 

假设

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

另一解决方案

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

在一些代码方面

  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(); } } 

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


UPDATE

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

  • 取消近距离活动
  • 从一个事件重新路由到另一个事件
  • 强制调用Dispose
  • 正如Servy所指出的那样:维护不友好(要检查哪个表格已关闭)