events - C++/CLI 事件是否有任何监听器?

标签 events c++-cli listeners

在 C# 中,我可以检查事件是否有任何监听器:

C# 示例:

public static event EventHandler OnClick;

if (OnClick != null)
    OnClick(null, new EventArgs() );

在 C++/CLI 中,不需要检查事件是否为空。

C++/CLI 示例:
delegate void ClickDelegate( Object^ sender, MyEventArgs^ e );
event ClickDelegate^ OnClick;

OnClick (sender, args);

但是,在我正在处理的项目中,如果没有监听器,我不想构造 MyEventArgs 对象。

如何确定 OnClick 在 C++ 中是否有任何监听器?

最佳答案

基于与@BenVoigt 对@svick 的原始答案和新的MSDN article on C++/CLI events 的评论讨论,我创建了一个如何正确执行此操作的最小示例。此代码在面向 .NET 4.5 的 Visual Studio 2013 CLR 项目模板中编译和运行。我没有在其他运行时和目标上进行测试,但它只使用基本的 .NET 组件。
TL;博士:

  • 将支持字段设为私有(private)
  • 使用 System::Threading::Monitor 锁定每个添加、删除和引发调用
  • 使用标准事件处理程序约定:
      void MyEventHandler(Object ^sender, MyEventArgs ^e);
    
  • 使用+=-=除非支持字段是 nullptr

  • 我的解决方案:
    // compile with: /clr
    #include "stdafx.h"
    
    using namespace System;
    using System::Threading::Monitor;
    
    public delegate void MyDelegate(Object ^sender, EventArgs ^e);
    
    ref class EventSource {
    private:
        MyDelegate ^myEvent;
        Object ^eventLock;
    
    public:
        EventSource()
        {
            eventLock = gcnew Object();
        }
    
        event MyDelegate^ Event {
            void add(MyDelegate^ handler) {
                Monitor::Enter(eventLock);
                if (myEvent == nullptr)
                {
                    myEvent = static_cast<MyDelegate^> (
                                Delegate::Combine(myEvent, handler));
                }
                else
                {
                    myEvent += handler;
                }
                Monitor::Exit(eventLock);
            }
    
            void remove(MyDelegate^ handler) {
                Monitor::Enter(eventLock);
                if (myEvent != nullptr)
                {
                    myEvent -= handler;
                }
                Monitor::Exit(eventLock);
            }
    
            void raise(Object ^sender, EventArgs ^e) {
                Monitor::Enter(eventLock);
                if (myEvent != nullptr)
                    myEvent->Invoke(sender, e);
                Monitor::Exit(eventLock);
            }
        }
    
        void Raise()
        {
            Event(this, EventArgs::Empty);
        }
    };
    
    public ref struct EventReceiver {
        void Handler(Object ^sender, EventArgs ^e) {
            Console::WriteLine("In event handler");
        }
    };
    
    int main() {
        EventSource ^source = gcnew EventSource;
        EventReceiver ^receiver = gcnew EventReceiver;
    
        // hook event handler
        source->Event += gcnew MyDelegate(receiver, &EventReceiver::Handler);
    
        // raise event
        source->Raise();
    
        // unhook event handler
        source->Event -= gcnew MyDelegate(receiver, &EventReceiver::Handler);
    
        // raise event, but no handlers
        source->Raise();
    }
    

    关于events - C++/CLI 事件是否有任何监听器?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8413109/

    相关文章:

    javascript - 如何获取点击链接的 ID,然后在 CSS 中设置样式

    dll - 如何使用 Marshal 类编译 C++ DLL

    c++-cli - 将矩阵定义为数组的数组并在 C++ 中计算其逆矩阵

    java - 我的 jComboBox 不对我的 keyListener 使用react,并且 actionPerform 执行奇怪的操作

    asp.net-mvc - ASP.NET MVC PostAuthorizeRequest(和其他事件)未触发

    wpf - 在 WPF 中存储事件处理程序方法的位置 - MVVM

    javascript - 使用 anchor 到达页面时触发事件

    events - 从 C++/CLI 引发事件的正确方法?

    java - JFrame 显示 - 鼠标监听器

    java - 删除键时如何从 LinkedHashMap 对象中删除监听器