可以“分拆”几个GUI线程? (不在Application.Run停止系统)

时间:2008-08-05 21:19:37

标签: c# .net winforms

我的目标

我想拥有一个主处理线程(非GUI),并且能够根据需要在自己的后台线程中分离GUI,并让我的主非GUI线程继续工作。换句话说,我希望我的主非GUI线程成为GUI线程的所有者,反之亦然。我不确定Windows Forms(?)

是否可行

背景

我有一个基于组件的系统,其中控制器动态加载程序集并实例化并运行使用单个方法IComponent实现公共DoStuff()接口的类。

通过xml配置文件和添加包含IComponent的不同实现的新程序集来配置加载的组件。组件为主应用程序提供实用程序功能。虽然主程序正在做这件事,例如控制核电站,组件可能正在执行公用事业任务(在他们自己的线程中),例如清理数据库,发送电子邮件,在打印机上打印有趣的笑话,你有什么。我想要的是让这些组件中的一个能够显示GUI,例如,具有所述电子邮件发送组件的状态信息。

整个系统的生命周期如下

  1. 申请开始。
  2. 检查要加载的组件的配置文件。加载它们。
  3. 对于每个组件,运行DoStuff()进行初始化,并使其在自己的线程中实现自己的生命。
  4. 永远继续做主要应用 - 工作之王。
  5. 如果组件在DoStuff()中启动GUI,我还无法成功执行第3点。它只是暂停,直到GUI关闭。直到GUI关闭,程序才会进入第4点。

    如果允许这些组件启动它们自己的Windows窗体GUI,那就太棒了。

    问题

    当组件尝试在DoStuff()中启动GUI时(确切的代码行是组件运行Application.Run(theForm)时),组件因此我们的系统“挂起”{{1直到GUI关闭为止。好吧,正如预期的那样,刚启动的GUI工作正常。

    组件示例。一个与GUI没有任何关系,而第二个则是一个可爱的窗户,里面有粉红色的蓬松兔子。

    Application.Run()

    我试过这个没有运气。即使我尝试在其自己的线程中启动GUI,执行也会暂停,直到GUI关闭。

    public class MyComponent1: IComponent
    {
        public string DoStuff(...) { // write something to the database  }
    }
    
    public class MyComponent2: IComponent
    {
        public void DoStuff()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new Form());
    
            // I want the thread to immediately return after the GUI 
            // is fired up, so that my main thread can continue to work.
        }
    }
    

    是否可以分离GUI并在public void DoStuff() { new Thread(ThreadedInitialize).Start() } private void ThreadedInitialize() { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); Application.Run(new Form()); } 之后返回?

3 个答案:

答案 0 :(得分:11)

Application.Run 方法显示一个(或多个)表单并启动标准消息循环,该循环一直运行直到所有表单都关闭。除非关闭所有表单或强制关闭应用程序,否则不能强制从该方法返回。

但是,您可以将 ApplicationContext (新的Form()的实例)传递给Application.Run方法,并且可以使用ApplicationContext一次启动多个表单。您的申请只会在所有申请被关闭时结束。见这里:http://msdn.microsoft.com/en-us/library/system.windows.forms.application.run.aspx

此外,您以非模态方式显示的任何表单将继续与主表单一起运行,这将使您拥有多个不会相互阻塞的窗口。我相信这实际上是你想要完成的事情。

答案 1 :(得分:0)

我确信如果你足够努力,这是可能的,但我认为这不是一个好主意。

'Windows'(您在屏幕上看到的)与流程高度耦合。也就是说,显示任何GUI的每个进程都应该有一个消息循环,它处理所有与创建和管理窗口有关的消息(例如“点击按钮”,“关闭应用程序”,“重绘屏幕” '等等。

因此,或多或少地假设如果您有任何消息循环,它必须在您的进程的生命周期中可用。例如,窗口可能会向您发送“退出”消息,您需要有一个消息循环来处理它,即使您在屏幕上没有任何内容。

你最好的选择就是这样:

制作一张永不显示的假表格,这是您的“主要应用” 启动 调用Application.Run并传入这个假表格。 在另一个线程中完成工作,并在需要执行Gui工作时在主线程上触发事件。

答案 2 :(得分:0)

我不确定这是否正确,但我记得只是通过新建表单并在其上调用newForm.Show()来运行控制台应用程序中的窗口表单,如果您的组件使用它而不是Application.Run()然后新表格不应该阻止。

当然,该组件将负责维护对其创建的表单的引用