我创建了一个 C# 控制台应用程序,通过订阅 Console.CancelKeyPress 事件来处理 Ctrl-C。当我执行(调试版本)应用程序时,进程中已经创建了 14 个线程。当我按下 Ctrl-C 时,会创建一个新的第 15 个线程并调用我的处理程序。我使用 sysinternals 中的进程资源管理器来查看进程的状态。
我很想知道 Ctrl-C 消息如何传递到进程以及如何创建附加线程的内部原理?我想,即使我不订阅事件,它仍然会创建一个额外的线程并退出进程。如何为应用程序设置处理 Ctrl-C 的默认机制。
我是一名 .net 开发人员,但想了解 Windows 操作系统的幕后工作原理。以上问题只是出于学习windows操作系统的好奇。
I created a C# console application to handle Ctrl-C by subscribing it to Console.CancelKeyPress event. When I executed (debug version) the application, there were 14 threads already created in the process. When I pressed Ctrl-C a new, 15th thread was created and my handler was invoked. I used process explorer from sysinternals to view the state of the process.
I am curious to know the internals on how the Ctrl-C message is delivered to a process and how the additional thread gets created? I guess, even if I do not subscribe to an event, it will still create an additional thread and exit the process. How is the default mechanism for handling Ctrl-C is setup for an application.
I am a .net developer but want to understand on how the windows operating system works under the hood. The above question is only out of curiosity to learn windows operating system.
发布评论
评论(2)
当 Windows 需要向控制台程序通知外部事件时,没有窗口消息循环来发送通知,因此 Windows 将在目标进程中创建一个线程来执行定义的任何回调函数。 CTRL+C 事件的默认处理程序仅调用
ExitProcess
,但挂钩CancelKeyPress
事件会调用 Win32SetConsoleCtrlHandler
函数与处理函数。处理函数的文档解释了它的工作原理:
请注意,Windows 注入到进程中的线程具有相当小的堆栈,因此 CLR 处理程序例程实际上会将线程池工作项排队以执行事件处理程序。这意味着 Windows 注入的线程和工作线程都可以被创建,从而使您在处理 CTRL+C 事件期间看到最多 2 个附加线程。
When Windows needs to notify a console program of an external event, there is no window message loop to send the notification to, so Windows will create a thread in the target process to execute whatever callback function is defined. The default handler for the CTRL+C event just calls
ExitProcess
, but hooking theCancelKeyPress
event calls the Win32SetConsoleCtrlHandler
function with a handler function.The documentation for the handler function explains how it works:
Note that the thread that Windows injects into your process has a fairly small stack, so the CLR handler routine actually queues up a Threadpool work item to execute your event handler. This means that the thread injected by Windows and a worker thread could both be created, causing you to see up to 2 additional threads during the processing of the CTRL+C event.
是的,Windows 启动一个线程来调用 SetConsoleCtrlHandler()。它由名为 ControlCHooker 的小型内部帮助器类的 Hook() 方法调用。它由 Cancel.CancelKeyPress 事件的 add() 访问器调用。 Windows 回调使您的事件处理程序运行。
像 Reflector 或 ILSpy 这样的优秀反汇编器以及参考源可以帮助您发现这些实现细节。
Yes, Windows starts up a thread to call the handler that's registered by SetConsoleCtrlHandler(). Which is called by the Hook() method of a little internal helper class named ControlCHooker. Which is called by the add() accessor of the Cancel.CancelKeyPress event. The Windows callback makes your event handler run.
A good disassembler like Reflector or ILSpy as well as the Reference Source can help you discover these implementation details.