C# 控制台应用程序:关闭窗口与程序结束
我正在编写一个小库来帮助管理Excel中的一些对象。我正在使用一个简单的控制台应用程序测试这个DLL,该应用程序调用库,然后打印结果。然后,我可以用任何一种典型的方式结束程序,通常是点击return(从而完成C# 控制台应用程序:关闭窗口与程序结束,c#,com,console-application,C#,Com,Console Application,我正在编写一个小库来帮助管理Excel中的一些对象。我正在使用一个简单的控制台应用程序测试这个DLL,该应用程序调用库,然后打印结果。然后,我可以用任何一种典型的方式结束程序,通常是点击return(从而完成ReadLine调用)或点击窗口的close按钮但是,对Excel实例的引用会根据程序的退出方式表现出不同的行为。 在我的程序中,如果找不到对Excel的现有引用,我将使用以下行: _app = new ExcelInterop.Application(); 其中,\u app是静态类或单
ReadLine
调用)或点击窗口的close按钮但是,对Excel实例的引用会根据程序的退出方式表现出不同的行为。
在我的程序中,如果找不到对Excel的现有引用,我将使用以下行:
_app = new ExcelInterop.Application();
其中,\u app
是静态类或单例类中的Microsoft.Office.Interop.Excel.Application
的一个实例(我已经尝试了这两种方法,两种方法都有相同的结果)
假设程序创建了自己的实例(但未找到已打开的实例):
- 如果通过单击关闭窗口按钮退出程序,实例将保持打开状态:
- 如果程序通过到达
块中的代码末尾而退出,则实例将被释放,并且不再显示在任务管理器中Main
也许最重要的是,这种行为的技术原因是什么?控制台模式程序对于从process 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键和单击Close按钮,尝试两种方法。您将看到终结器从未执行过。单击“关闭”按钮时,操作系统会在进程有机会正常关闭之前终止进程
COM包装器的终结器也存在同样的问题。它们无法执行,因此不会调用IUnknown::Release(),并且Office程序完全不知道客户端程序已不存在。Windows对废弃的进程外服务器有自己的清理功能,但由于某些神秘的原因,这对Office程序不起作用
这就解释了,修复它并不是那么容易。当单击“关闭”按钮时,必须运行该命令。如有必要,如果应用程序引用仍在作用域中,请将其设置为null,并强制终结器与GC.Collect()+GC.WaitForPendingFinalizers()一起运行。请记住,这只是一个创可贴,而不是修复。当用户在您忙于与Office程序对话时中止您的程序时,它将不起作用。避免控制台模式的项目是最好的。也许你可以整理一下像@jgok222这样的接近事件,这似乎是一个很好的结论,但是你知道在幕后到底发生了什么吗?最让人困惑的是,目前我还没有编写任何清理代码。我完全希望该实例在所有情况下都保持打开状态。我想我在推我不完全理解的代码时感到有点不安。回答得很好!正是我想要的。关闭按钮盒是否是控制台应用程序独有的?这是我在WPF中必须担心的事情吗?该应用程序将成为WPF关闭事件的一部分,它充分利用了WPF的关闭事件。GUI应用程序没有这个问题。太棒了,在这种情况下,我想我会创建一个公共清理方法,让任何控制台开发人员(我怀疑他们中的任何人)为自己的程序处理事件侦听器。@SandyGifford是“public cleanup method”正在实现
IDisposeable
接口,并将清理代码放入其中。然后,您的类的用户可以使用语句将包装器的实例放入他们自己的中,或者将他们的类IDisposeable
也放入其中并将其处理掉。