.NET 的事件机制

.NET's Event Mechanism

我目前看到的所有关于C#/.NET的书,在谈到事件的时候,
他们谈论创造消费事件。

我很想了解它在我们的代码背后是如何工作的——运行它的机制是什么。

我从 Windows 消息循环对所引发事件的行为类似于队列这一事实中略知一二。
例如,WM_KEYDOWN,或WM_LBUTTONDOWN,等等。

但是会发生什么,例如,如果我创建了一个不继承 class Control 的 class,并且这个 class 引发了一个事件?
(另一个 class,也没有继承 class Control,接收它)

引发的事件会通过消息循环吗?
听起来不太合逻辑..
(但假设该项目是一个 Windows Forms 项目,只有 2 个 classes - 发送者和接收者根本不是 GUI classes,而是简单的 class是你写的)

任何解释或link关于我们代码背后的机制的文章将不胜感激。

希望我没有正确理解您的问题。我想我们在谈论两件事。

首先 - C# 中事件的工作原理 第二 - 用 C# 编写的 WinForms 应用程序如何知道您何时单击了按钮。

C# 中的事件是它们自己独特的事物。您可以编写一个控制台应用程序、创建您自己的事件、收听它、触发它、响应它等等……这一切都可以正常工作。您通过调用 Add() 订阅事件,通过调用 Remove() 取消订阅。事件本身跟踪哪些方法正在侦听它,并在引发时调用所有这些方法。

Jon Skeet 解释得更好: How do C# Events work behind the scenes?

但这些事件只是 C# 代码。与您提到的 Win32 消息相关但又不同。在 Winforms 应用程序中,当用户单击按钮时,应用程序如何知道它?我们可以使用调试器(关闭 'My Code' https://msdn.microsoft.com/en-us/library/dn457346.aspx 选项)并在点击事件中设置断点,您将能够看到发生了什么。

所以在 Windows.Forms.Controls.ControlNativeWindow 中有一个 WndProc 方法接受一个 System.Windows.Forms.Message m。

在那之前是一个'debuggableCallback'方法。这反映了您对 Win32API 应用程序的期望。

来源: http://referencesource.microsoft.com/#System.Windows.Forms/winforms/Managed/System/WinForms/NativeWindow.cs,ad40308c5b6490dd

/// <include file='doc\NativeWindow.uex' path='docs/doc[@for="NativeWindow.DebuggableCallback"]/*' />
/// <devdoc>
///     Window message callback method. Control arrives here when a window
///     message is sent to this Window. This method packages the window message
///     in a Message object and invokes the wndProc() method. A WM_NCDESTROY
///     message automatically causes the releaseHandle() method to be called.
/// </devdoc>
/// <internalonly/>
private IntPtr DebuggableCallback(IntPtr hWnd, int msg, IntPtr wparam, IntPtr lparam) {

    // Note: if you change this code be sure to change the 
    // corresponding code in Callback above!

    Message m = Message.Create(hWnd, msg, wparam, lparam);

    try {
        if (weakThisPtr.IsAlive && weakThisPtr.Target != null) {
            WndProc(ref m);
        }
        else {
            DefWndProc(ref m);
        }
    }
    finally {
        if (msg == NativeMethods.WM_NCDESTROY) ReleaseHandle(false);
        if (msg == NativeMethods.WM_UIUNSUBCLASS) ReleaseHandle(true);
    }

    return m.Result;
}

因此,最终,如果您 运行 在 Windows 上,它是由您期望的相同 Win32 API 消息驱动的。只不过写的System.Windows.Forms类是为了封装我们的大部分。