我创建了一个C#控制台应用程序来处理 Ctrl - C ,方法是将它订阅到Console.CancelKeyPress事件。当我执行(调试版本)应用程序时,在该过程中已经创建了14个线程。当我按下 Ctrl - C 时,创建了一个新的第15个线程并调用了我的处理程序。我使用sysinternals中的process explorer来查看进程的状态。
我很想知道如何将 Ctrl - C 消息传递给进程以及如何创建其他线程的内部结构?我想,即使我没有订阅一个事件,它仍然会创建一个额外的线程并退出该进程。如何为应用程序设置处理 Ctrl - C 的默认机制。
我是.net开发人员,但想了解Windows操作系统的工作原理。以上问题仅仅是出于好奇学习Windows操作系统。
答案 0 :(得分:3)
当Windows需要通知控制台程序外部事件时,没有窗口消息循环来发送通知,因此Windows将在目标进程中create a thread执行定义的任何回调函数。 CTRL + C事件的默认处理程序只调用ExitProcess
,但挂钩CancelKeyPress
事件会使用处理函数调用Win32 SetConsoleCtrlHandler
函数。
handler function的文档解释了它的工作原理:
与SetConsoleCtrlHandler函数一起使用的应用程序定义函数。控制台进程使用此功能来处理进程接收的控制信号。收到信号后,系统会在进程中创建一个新线程来执行该功能。
请注意,Windows注入到您的进程中的线程具有相当小的堆栈,因此CLR处理程序例程实际上将Threadpool工作项排队以执行您的事件处理程序。这意味着可以创建Windows 和工作线程注入的线程,导致在处理CTRL + C事件期间最多可以看到2个额外的线程。
答案 1 :(得分:1)
是的,Windows启动一个线程来调用由SetConsoleCtrlHandler()注册的处理程序。这是由名为ControlCHooker的一个小内部帮助器类的Hook()方法调用的。这是由Cancel.CancelKeyPress事件的add()访问者调用的。 Windows回调使您的事件处理程序运行。
像Reflector或ILSpy这样的好的反汇编程序以及参考源可以帮助您发现这些实现细节。