Подписаться на событие много раз с EventHandlerList - PullRequest
1 голос
/ 09 мая 2011

Цель: я хочу много раз подписаться на одно и то же событие в разных классах. У меня есть следующий класс:

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();
        }
    }
}

SyncOperation:

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)
    {...}
}

При вызове операции. Execute (); не все полученные события генерируются в классе SyncOperation.

Я что-то упустил?

1 Ответ

0 голосов
/ 09 мая 2011

Я сравнил ваш код с известным хорошим примером, и у меня есть сомнения относительно private readonly string OnReceivedEventName как ключ-объект.Вы полагаетесь на интернирование строк здесь, «нормальный» является статическим объектом.

И это заставляет меня задуматься, являются ли обычные сгенерированные события потокобезопасными.Не удалось найти ссылку так быстро, но для диагностики:

public event MessageEventHandler OnReceived;

У вас может быть состояние гонки, но это будет очень редко (и его легко минимизировать / устранить).Все ли обработчики вызваны?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...