首页 > 解决方案 > 订阅/取消订阅列表中的事件

问题描述

我有一个对象列表,我想为每个对象订阅/取消订阅一个事件(通过委托,因为我需要将额外的参数传递给方法)。所以我有这样的事情:

 public void MonitoringCtrl(bool monitoringOn)
    {
        foreach (var mh in monHandlers)
        {
            evHandler = (sender, e) => OnNotification(sender, e, mh);

            if (monitoringOn)
            {
                //subscribe to event
                mh.monitoredItem.Notification += evHandler;
            }
            else
            {
                //unsubscribe
                mh.monitoredItem.Notification -= evHandler;
            }
        }

        //do other stuff
    }

这在订阅时有效,但在取消订阅时不起作用,大概是因为我在 foreach 中重新声明了 evHandler。如何保存对 evHandler 的引用?

标签: c#event-handling

解决方案


这是因为在第二次调用时MonitoringCtrl()(当您传递false取消订阅时),会创建一个新的事件处理程序。但是该新实例不会取消订阅之前附加的事件处理程序实例。

您不需要为循环中的每个元素创建新的事件处理程序,也不得创建新的事件处理程序来取消订阅。您可以为所有事件保留一个事件处理程序作为成员变量。但是通过绑定到这样的方法更容易做到这一点:

public void MonitoringCtrl(bool monitoringOn)
{
    foreach (var mh in monHandlers)
    {
        if (monitoringOn)
        {
            //subscribe to event
            mh.monitoredItem.Notification += HandleNotification;
        }
        else
        {
            //unsubscribe
            mh.monitoredItem.Notification -= HandleNotification;
        }
    }

    //do other stuff
}

private void HandleNotification(object sender, EventArgs args)
{
    //do event stuff
}

更新我刚刚看到您需要使用委托来获取其他参数

您可以使用本地函数来捕获父方法的属性,但在您的情况下,您需要捕获循环变量。那是行不通的,所以我会尝试找到一种方法来摆脱mh困境,sender因为它似乎是相关的。你想用 lambda ( )传递the和它sendermonitoredItem父级吗?monitorHandlermh


推荐阅读