c# -是否可以剥离几个GUI线程?(在Application.Run时不停止系统)

Translate

我的目标

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

背景

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

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

整个系统的生命周期如下所示

  1. 应用程序启动。
  2. 检查配置文件以加载组件。加载它们。
  3. 对于每个组件,运行DoStuff()对其进行初始化,并使其在自己的线程中过着自己的生活。
  4. 永远继续做主要的应用程序-繁重的工作。

如果组件启动了一个GUI,我还无法成功执行第3点DoStuff()。它只是停止直到GUI关闭。直到关闭GUI,程序才会前进到第4点。

如果允许这些组件启动自己的Windows Forms GUI,那将是非常不错的。

问题

当组件尝试启动一个GUI时DoStuff()(确切的代码行是组件运行的时间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()?

This question and all comments follow the "Attribution Required."

所有的回答

Translate

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

但是,您可以通过ApplicationContext(将新Form()插入到Application.Run方法和ApplicationContext中)可以一次启动多个表单。仅当所有这些应用程序都关闭时,您的应用程序才会结束。看这里:http://msdn.microsoft.com/zh-CN/library/system.windows.forms.application.run.aspx

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

来源
Translate

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

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

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

最好的选择是这样做:

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

来源
Translate

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

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

来源