为什么有些代码只在我用C#创建/运行表单时才有效?

时间:2015-04-07 23:20:35

标签: c# winforms ssh ssh.net

在将应用程序变成更像后台任务的过程中,我注意到了一些奇怪的行为。当我运行这样的东西时它工作正常(类似于我正在修改的旧代码):

using (Foo f = new Foo(stuff)) {
  f.doSomething();

  Application.EnableVisualStyles();
  Application.SetCompatibleTextRenderingDefault(false);
  Application.Run(new Form());
}

在后台运行此操作的第一步当然是删除对表单/呈现的引用:

using (Foo f = new Foo(stuff)) {
  f.doSomething();
}
但是,这种方式不起作用。当我运行它时,我使用的库(与Windows窗体没有任何关系)不再正常工作。这没有我计划做的任何其他改变。只删除这三行。如果它是相关的,实际代码中的Foo是一个创建SSH隧道的类(使用SSH.NET库),但它不是通过表单/设计器中的任何代码(直接或间接)引用的,它只需要设置/拆除就可以建立连接。

错误发生在建立隧道连接之前,而是在尝试连接到远程主机并转发端口时。该库报告已建立连接(IsConnectedtrue),但是当启动端口转发时,它会报告包含消息"Session is not connected"

的异常

1 个答案:

答案 0 :(得分:1)

将您的应用程序转换为后台服务并不像删除这三行那么简单。特别是,Application.Run(new Form)是根据MSDN启动应用程序主线程的原因:

  

开始在当前线程上运行标准的应用程序消息循环,并使指定的表单可见。

https://msdn.microsoft.com/en-us/library/ms157902(v=vs.110).aspx

您可以查看重载Application.Run(),它将在没有表单的情况下启动主线程 - 但是您将遇到正确终止该线程的问题。至少,您可以验证您的代码确实在没有明显显示表单的情况下工作。唯一需要注意的是,您的主Form还有其他对您图书馆的调用,现在必须在其他地方进行处理。

  

在基于Win32或Windows窗体的应用程序中,消息循环是代码中的例程,用于处理用户事件,例如鼠标单击和键盘敲击。每个运行的基于Windows的应用程序都需要一个活动的消息循环,称为主消息循环。当主消息循环关闭时,应用程序退出。在Windows窗体中,当调用Exit方法时,或者在运行主消息循环的线程上调用ExitThread方法时,将关闭此循环。

     

大多数Windows窗体开发人员不需要使用此版本的方法。您应该使用Run(Form)重载来启动具有主窗体的应用程序,以便在关闭主窗体时应用程序终止。对于所有其他情况,请使用Run(ApplicationContext)重载,该重载支持提供ApplicationContext对象以更好地控制应用程序的生命周期。

https://msdn.microsoft.com/en-us/library/ms157900(v=vs.110).aspx

说实话,你可能最好只是启动一个新的Windows服务或WCF项目。