我写了这个小程序来证明问题的重点:
using System;
using System.IO;
using System.Threading;
class Program
{
static void Main(string[] args)
{
using (var disp = new MyDisp())
{
using (var ewhLocalExit = new EventWaitHandle(false, EventResetMode.ManualReset))
{
Console.WriteLine("Enter Ctrl+C to terminate the app.");
Console.CancelKeyPress += (_, e) =>
{
e.Cancel = true;
ewhLocalExit.Set();
};
ewhLocalExit.WaitOne();
}
}
File.AppendAllText("Log.txt", "Terminated.\n");
}
}
class MyDisp : IDisposable
{
public MyDisp()
{
File.AppendAllText("Log.txt", "Started.\n");
}
public void Dispose()
{
File.AppendAllText("Log.txt", "Disposed.\n");
}
}
Run Code Online (Sandbox Code Playgroud)
当我运行它并按Ctrl + C时,我看到"Started.Disposed.Terminated".在Log.txt中
当我运行它并用鼠标关闭它时,我只看到"已启动".
如何优雅地退出,这样我至少可以看到"Disposed".?
您可以使用 DLLImport 导入 SetConsoleControlHandler 并使用它为关闭事件(和其他事件)注册事件处理程序,这里有一个示例片段,显示它的工作原理(当您单击 X 关闭控制台时,它将在 Log.txt 中写入关闭) ):
class Program
{
[DllImport("Kernel32")]
public static extern bool SetConsoleCtrlHandler(HandlerRoutine Handler, bool Add);
// A delegate type to be used as the handler routine
// for SetConsoleCtrlHandler.
public delegate bool HandlerRoutine(CtrlTypes CtrlType);
// An enumerated type for the control messages
// sent to the handler routine.
public enum CtrlTypes
{
CTRL_C_EVENT = 0,
CTRL_BREAK_EVENT,
CTRL_CLOSE_EVENT,
CTRL_LOGOFF_EVENT = 5,
CTRL_SHUTDOWN_EVENT
}
private static bool ConsoleCtrlCheck(CtrlTypes ctrlType)
{
if (ctrlType == CtrlTypes.CTRL_CLOSE_EVENT)
File.AppendAllText(@"Log.txt", "closed");
return true;
}
private static void Main(string[] args)
{
SetConsoleCtrlHandler(new HandlerRoutine(ConsoleCtrlCheck), true);
Console.WriteLine("Close me");
Console.ReadLine();
}
}
Run Code Online (Sandbox Code Playgroud)