使用 EventHandlerList 多次订阅事件

本文关键字:事件 EventHandlerList 使用 | 更新日期: 2023-09-27 17:56:01

目标:我想在不同的类中多次订阅同一事件。我有以下课程:

public class MyEngine : IEngine
{
    private EventHandlerList _events = new EventHandlerList();
    protected EventHandlerList Events
    {
        get
        {
            return _events;
        }
    }
    private readonly string OnReceivedEventName = "OnReceived";
    public event MessageEventHandler OnReceived
    {
        add
        {
            lock (this)
            {
                Events.AddHandler(OnReceivedEventName, value);
            }
        }
        remove
        {
            lock (this)
            {
                Events.RemoveHandler(OnReceivedEventName, value);
            }
        }
    }
    protected internal virtual void MessageReceived(MessageEventArgs e)
    {
        var handler = Events[OnReceivedEventName] as MessageEventHandler;
        TryFireMessageEvent(handler, e);
    }
    private void TryFireMessageEvent(MessageEventHandler handler, MessageEventArgs e)
    {
        try
        {
            if (handler != null)
                handler.Invoke(this, e);
        }
        catch (Exception ex)
        {
            log.Error("Message Received - Exception caught", ex);
            ErrorOccurred(ex);
        }
    }
}

主模块有一个 IEngine 的实例:

public class MyProvider
{
    protected internal IEngine Engine { get; set; }
    public MyProvider(IEngine engine)
    {
        Engine = engine;
        engine.OnReceived += Engine_Received;
    }
    protected internal void Engine_Received(IEngine engine, MessageEventArgs args)
    {...}
}

我还有一个函数"DoAction",可以创建一个操作并注入引擎:

public class MyProvider
{
    ....
    public Result DoAction()
    {
        using (var operation = new SyncOperation(Engine))
        {
            operationResult = operation.Execute();
        }
    }
}

同步操作:

public class SyncOperation : IDisposable
{
    private IEngine _engine;
    public SyncOperation (IEngine engine)
    {
        Ensure.NotNull(engine, "engine");
        _engine = engine;
        _engine.OnReceived += Engine_OnReceived;
    }
    internal void Engine_OnReceived(IEngine engine, MessageEventArgs args)
    {...}
}

调用操作时。执行();并非所有收到的事件都在 SyncOperation 类上引发。

我错过了什么吗?

使用 EventHandlerList 多次订阅事件

我将您的代码与已知良好的示例进行了比较,我对private readonly string OnReceivedEventName作为对象键表示怀疑。你在这里依靠字符串实习,"正常"是一个静态对象。

这让我想知道正常生成的事件是否是线程安全的。无法这么快找到参考,但作为诊断:

public event MessageEventHandler OnReceived;

那时你可能会有一个竞争条件,但这将是非常罕见的(并且很容易最小化/消除)。是否调用所有处理程序?