【问题标题】:Console Application: Closing Window vs End of Program控制台应用程序:关闭窗口与程序结束
【发布时间】:2014-07-30 16:29:43
【问题描述】:

我正在编写一个小型库来帮助管理 Excel 中的一些对象。我正在使用一个简单的控制台应用程序来测试这个 DLL,该应用程序调用库,然后将结果打印出来。然后我可以以任何典型的方式结束程序,通常是通过点击返回(从而完成ReadLine 调用)或点击窗口的关闭按钮。 但是,对 Excel 实例的引用会根据程序退出的方式而有所不同。

在我的程序中,如果找不到对 Excel 的现有引用,我使用以下行:

_app = new ExcelInterop.Application();

其中_app 是静态类或单例类中Microsoft.Office.Interop.Excel.Application 的一个实例(我都尝试过,两者的结果相同)。

假设程序创建了它自己的实例(并且没有找到已经打开的实例):

  • 如果通过单击关闭窗口按钮退出程序,实例将保持打开状态
  • 如果程序通过到达Main 块中的代码末尾而退出,则该实例已释放,并且不再出现在任务管理器中

有没有办法让所有程序结束都像后一种情况一样?此外,这个 DLL 将继续在 WPF 应用程序中使用,在 WPF 中是否有类似的问题? 或者在逃?

也许最重要的是,这种行为的技术原因是什么?

【问题讨论】:

  • 也许在stackoverflow.com/questions/474679/capture-console-exit-c-sharp这样的密切活动中整理一下
  • @jgok222 这似乎是一个很好的结论,但你知道引擎盖下到底发生了什么吗?最令人困惑的部分是我目前还没有编写任何清理代码。我完全期望该实例在所有情况下都保持打开状态。我想我对推送我不完全理解的代码感到有些不安。

标签: c# com console-application


【解决方案1】:

控制台模式程序对于单元线程的进程外 COM 服务器所需的 COM 互操作包装对象来说是一个非常不利的地方。这个程序演示了这个问题:

using System;

class Program {
    static void Main(string[] args) {
        var prg = new Program();
        Console.ReadLine();
    }
    ~Program() {
        Console.WriteLine("Clean-up completed");
        System.Threading.Thread.Sleep(1500);
    }
}

尝试两种方法,按 Enter 并单击关闭按钮。你会看到终结器永远不会被执行。当您单击“关闭”按钮时,操作系统会在有机会正常关闭之前终止该进程。

COM 包装器的终结器存在同样的问题。它们无法执行,因此不会调用 IUnknown::Release() 并且 Office 程序完全不知道客户端程序不再存在。 Windows 对废弃的进程外服务器有自己的清理功能,但由于某些其他神秘的原因,它不适用于 Office 程序。

这就解释了,修复它并不是那么容易。您必须在单击关闭按钮时运行 register a callback。如有必要,如果 app 引用仍在范围内,则将其设置为 null 并强制终结器使用 GC.Collect() + GC.WaitForPendingFinalizers() 运行。请记住,这只是一个创可贴,而不是修复。当您忙于与 Office 程序交谈时用户中止您的程序时,它将不起作用。最好避免使用控制台模式项目。

【讨论】:

  • 优秀的答案!正是我想要的。关闭按钮盒是控制台应用程序独有的吗?这是我在 WPF 中必须担心的事情吗?将成为其中一部分的应用程序充分利用了 WPF 的关闭事件。
  • GUI 应用没有这个问题。
  • 太棒了,在这种情况下,我想我会创建一个公共清理方法,并让任何控制台开发人员(我怀疑永远不会有)为他们自己的程序处理事件侦听器。
  • @SandyGifford “公共清理方法”的标准是实现IDisposeable 接口并将清理代码放入其中。然后,您的类的用户可以将您的包装器的实例放在他们自己的 using 语句中,或者也将他们的类设为 IDisposeable 并在那里处理它。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-06-21
  • 1970-01-01
  • 2019-01-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多