关于c#:可以“剥离”几个GUI线程吗? (不通过Application.Run停止系统)

关于c#:可以“剥离”几个GUI线程吗? (不通过Application.Run停止系统)

Possible to “spin off” several GUI threads? (Not halting the system at Application.Run)

我的目标

我想要一个主处理线程(非GUI),并能够根据需要在其自己的后台线程中剥离GUI,并使我的主要非GUI线程保持正常工作。换句话说,我希望我的主要非GUI线程成为GUI线程的所有者,而不是相反。我不确定Windows Forms(?)甚至可能做到这一点

背景

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

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

整个系统的寿命如下所示

  • 应用程序启动。
  • 检查配置文件以加载组件。加载它们。
  • 对于每个组件,运行DoStuff()对其进行初始化,并使其在各自的线程中过着自己的生活。
  • 永远继续做主要的应用程序-繁重的工作。
  • 如果组件启动DoStuff()中的GUI,我还无法成功执行第3点。它只是停止,直到关闭GUI。直到GUI关闭,程序才会前进到第4点。

    如果允许这些组件启动它们自己的Windows Forms GUI,那将是很好的。

    问题

    当组件尝试启动DoStuff()中的GUI时(确切的代码行是当组件运行Application.Run(theForm)时),该组件及其系统因此在Application.Run()行处"挂起",直到GUI关闭。好吧,刚刚启动的GUI可以正常工作。

    组件示例。其中一个与GUI无关,而第二个则触发了一个可爱的带有粉红色蓬松兔子的窗户。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    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关闭为止。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    public void DoStuff()
    {
        new Thread(ThreadedInitialize).Start()
    }

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

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


    Application.Run方法显示一个(或多个)表单并启动标准消息循环,该循环运行直到关闭所有表单为止。您不能通过关闭所有表单或强制关闭应用程序来强制返回该方法。

    但是,您可以将ApplicationContext(新Form()的instad)传递给Application.Run方法,并且ApplicationContext可用于一次启动多个表单。仅当所有这些应用程序都关闭时,您的应用程序才会结束。参见此处:http://msdn.microsoft.com/zh-cn/library/system.windows.forms.application.run.aspx

    此外,您非模态显示的任何表单都将继续与主表单一起运行,这将使您拥有不止一个相互阻塞的多个窗口。我相信这实际上是您想要实现的目标。


    我不确定这是否正确,但是我记得从控制台应用程序运行窗口表单,方法是仅更新表单并在其上调用newForm.Show(),如果您的组件使用的是它而不是Application.Run(),则新表格不应阻止。

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


    我敢肯定,如果您足够努力地攻克它,这是可能的,但是我建议这不是一个好主意。

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

    因此,或多或少地假定如果您有任何消息循环,则该消息循环在整个过程的生命周期中必须可用。例如,Windows可能会向您发送"退出"消息,并且即使屏幕上没有任何内容,您也需要有一个消息循环来处理该消息。

    最好的选择是这样做:

    制作一个永远不会显示的假表格,这是您的"主应用程序"
    启动
    调用Application.Run并通过此假表格传递。
    在另一个线程中进行工作,并在需要执行Gui任务时在主线程中触发事件。


    推荐阅读