AppDomain
的ProcessExit
事件:class Program
{
static void Main(string[] args)
{
AppDomain.CurrentDomain.ProcessExit += new EventHandler(CurrentDomain_ProcessExit);
// do some work
}
static void CurrentDomain_ProcessExit(object sender, EventArgs e)
{
Console.WriteLine("exit");
}
}
更新
这是一个完整的示例程序,其中一个空的“消息泵”在单独的线程上运行,允许用户在控制台中输入退出命令以正常关闭应用程序。在 MessagePump 循环之后,您可能希望以良好的方式清理线程使用的资源。最好在那里做这件事,而不是在 ProcessExit 中做,原因如下:
以下是代码:
class Program
{
private static bool _quitRequested = false;
private static object _syncLock = new object();
private static AutoResetEvent _waitHandle = new AutoResetEvent(false);
static void Main(string[] args)
{
AppDomain.CurrentDomain.ProcessExit += new EventHandler(CurrentDomain_ProcessExit);
// start the message pumping thread
Thread msgThread = new Thread(MessagePump);
msgThread.Start();
// read input to detect "quit" command
string command = string.Empty;
do
{
command = Console.ReadLine();
} while (!command.Equals("quit", StringComparison.InvariantCultureIgnoreCase));
// signal that we want to quit
SetQuitRequested();
// wait until the message pump says it's done
_waitHandle.WaitOne();
// perform any additional cleanup, logging or whatever
}
private static void SetQuitRequested()
{
lock (_syncLock)
{
_quitRequested = true;
}
}
private static void MessagePump()
{
do
{
// act on messages
} while (!_quitRequested);
_waitHandle.Set();
}
static void CurrentDomain_ProcessExit(object sender, EventArgs e)
{
Console.WriteLine("exit");
}
}
这是一个完整的、非常简单的.NET解决方案,可在所有版本的Windows中运行。只需将其粘贴到新项目中,运行它并尝试使用Ctrl + C查看它如何处理:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
namespace TestTrapCtrlC{
public class Program{
static bool exitSystem = false;
#region Trap application termination
[DllImport("Kernel32")]
private static extern bool SetConsoleCtrlHandler(EventHandler handler, bool add);
private delegate bool EventHandler(CtrlType sig);
static EventHandler _handler;
enum CtrlType {
CTRL_C_EVENT = 0,
CTRL_BREAK_EVENT = 1,
CTRL_CLOSE_EVENT = 2,
CTRL_LOGOFF_EVENT = 5,
CTRL_SHUTDOWN_EVENT = 6
}
private static bool Handler(CtrlType sig) {
Console.WriteLine("Exiting system due to external CTRL-C, or process kill, or shutdown");
//do your cleanup here
Thread.Sleep(5000); //simulate some cleanup delay
Console.WriteLine("Cleanup complete");
//allow main to run off
exitSystem = true;
//shutdown right away so there are no lingering threads
Environment.Exit(-1);
return true;
}
#endregion
static void Main(string[] args) {
// Some biolerplate to react to close window event, CTRL-C, kill, etc
_handler += new EventHandler(Handler);
SetConsoleCtrlHandler(_handler, true);
//start your multi threaded program here
Program p = new Program();
p.Start();
//hold the console so it doesn’t run off the end
while(!exitSystem) {
Thread.Sleep(500);
}
}
public void Start() {
// start a thread and start doing some processing
Console.WriteLine("Thread started, processing..");
}
}
}
这个应用程序是一个服务器,只要系统关闭或者它接收到 Ctrl+C 或者控制台窗口被关闭,它就会一直运行。
由于这个应用程序的特殊性质,它不可避免地无法“优雅”地退出。(可能可以编写另一个应用程序来发送“服务器关闭”消息,但这对于一个应用程序来说过于繁琐,并且在某些情况下仍然不足以解决问题,比如当服务器(实际上是操作系统)正在关闭时。)
因此,我添加了一个“ConsoleCtrlHandler”,在其中停止我的线程并清理我的 COM 对象等...
Public Declare Auto Function SetConsoleCtrlHandler Lib "kernel32.dll" (ByVal Handler As HandlerRoutine, ByVal Add As Boolean) As Boolean
Public Delegate Function HandlerRoutine(ByVal CtrlType As CtrlTypes) As Boolean
Public Enum CtrlTypes
CTRL_C_EVENT = 0
CTRL_BREAK_EVENT
CTRL_CLOSE_EVENT
CTRL_LOGOFF_EVENT = 5
CTRL_SHUTDOWN_EVENT
End Enum
Public Function ControlHandler(ByVal ctrlType As CtrlTypes) As Boolean
.
.clean up code here
.
End Function
Public Sub Main()
.
.
.
SetConsoleCtrlHandler(New HandlerRoutine(AddressOf ControlHandler), True)
.
.
End Sub
这个设置似乎完美地解决了问题。在这里有一个链接,链接到相同功能的一些 C# 代码。
//hold the console so it doesn’t run off the end
while(!exitSystem) {
Thread.Sleep(500);
}
以防止控制台窗口意外关闭。 - Susan Wang对于CTRL+C的情况,你可以使用以下代码:
// Tell the system console to handle CTRL+C by calling our method that
// gracefully shuts down.
Console.CancelKeyPress += new ConsoleCancelEventHandler(Console_CancelKeyPress);
static void Console_CancelKeyPress(object sender, ConsoleCancelEventArgs e)
{
Console.WriteLine("Shutting down...");
// Cleanup here
System.Threading.Thread.Sleep(750);
}
如果您正在使用控制台应用程序并且正在发送消息,则可以使用WM_QUIT消息。
注:本句中pump messages一词不好翻译,根据上下文和it技术常识猜测为“发送消息”的意思。