可能“剥离”几个GUI线程? (不要在Application.Run中停止系统)

我的目标

我想有一个主要的处理线程(非GUI),并且能够根据需要在各自的后台线程中分离GUI,并让我的主要非GUI线程继续工作。换句话说,我希望我的主要非GUI线程是GUI线程的所有者,而不是相反。我不确定这甚至可以使用Windows窗体(?)

背景</强>

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

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

整个系统的使用期限如下所示

  1. 申请开始。
  2. 检查要加载的组件的配置文件。加载它们。
  3. 对于每个组件,运行 DoStuff()以初始化它并使其在自己的线程中生活。
  4. 永远继续做主要的应用程序之王。

如果组件在 DoStuff()中触发GUI,我还没有成功执行第3点。它只是在GUI关闭之前停止。直到GUI关闭,程序才进入第4点。

如果允许这些组件启动它们自己的Windows窗体GUI,那将是非常好的。

问题</强>

当组件尝试在 DoStuff()中启动GUI时(确切的代码行是组件运行 Application.Run(theForm))时,组件我们的系统在 Application.Run()行挂起,直到GUI被关闭。那么,正如预期的那样,刚启动的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,执行也会暂停,直到GUI被关闭。

public void DoStuff()
{
    new Thread(ThreadedInitialize).Start()
}

private void ThreadedInitialize()
{
    Application.EnableVisualStyles();
    Application.SetCompatibleTextRenderingDefault(false);
    Application.Run(new Form());
}

是否可以剥离GUI并在 Application.Run()之后返回?

0
额外 编辑
意见: 3

3 答案

我敢肯定,如果你足够强硬,这是可能的,但我建议这不是一个好主意。

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

正因为如此,或多或少的假设,如果你有任何消息循环,它必须在你的过程的一生中可用。例如,Windows可能会向您发送“退出”消息,并且您需要有一个消息循环可用于处理该消息,即使您在屏幕上没有任何内容。

你最好的选择就是这样做:

制作一个永远不会显示的假表单,这是您的“主要应用程序” 启动 调用Application.Run并传入这个伪造的表单。 在另一个线程中执行你的工作,当你需要执行Gui的东西时,在主线程中触发事件。

0
额外
实际上,窗口耦合到线程,而不是进程。每个进程可以有多个消息循环,它可以让你有几个完全独立的窗口。
额外 作者 Garo Yeriazarian,

Application.Run method displays one (or more) forms and initiates the standard message loop which runs until all the forms are closed. You cannot force a return from that method except by closing all your forms or forcing an application shutdown.

You can, however, pass an ApplicationContext (instad of a new Form()) to Application.Run method and ApplicationContext can be used to launch several forms at once. Your application will only end when all of those are closed. See here: http://msdn.microsoft.com/en-us/library/system.windows.forms.application.run.aspx

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

0
额外

我不知道这是否正确,但是我记得只是通过新建表单并调用newForm.Show()来从控制台应用程序运行窗口表单,如果您的组件使用该窗体而不是Application.Run(),那么新表格不应该阻止。

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

0
额外