Переключить делегат события - PullRequest
0 голосов
/ 31 мая 2018

Я использую видеодекодер, который отправляет событие NewFrame каждый раз, когда создается кадр.

Поскольку мне нужно выполнить некоторые задачи инициализации при первом запуске, мне нужно использовать перехват этогособытие кадра к функции playingStarted, затем подключите его к другой функции, которая будет imageReceived.

Итак, у меня есть это:

Action<byte[]> currentNewFrameDelegate;

MyClass() {
    currentNewFrameDelegate = playingStarted;
    decoder.NewFrame += currentNewFrameDelegate; // when a new frame is received
}

playingStarted(byte[] image) {
    SomeInitializationTasks();
    processImage(image); // Process that image anyway
    currentNewFrameDelegate = imageReceived; // Switch to a normal image processing
}

imageReceived(byte[] image) {
    processImage(image);
}

К сожалению, это не работаеттаким образом ... Функция playingStarted по-прежнему выполняется каждый раз при получении NewFrame.

Поскольку у меня есть несколько мест, где я хочу переключить этого делегата обратно на playingStarted, я не хочуиспользуйте взлом - = then + =, чтобы предотвратить подписку на несколько событий, поскольку это делает код менее читабельным.

Как я могу переключить делегат события таким образом?


Редактировать:

Это может быть достигнуто следующим образом:

decoder.NewFrame += img => currentNewFrameDelegate?.Invoke(img);

Однако, он создает двойной вызов каждый раз, когда происходит событие ... Так что я, к сожалению, закончил тем, что написал это:

Action<byte[]> current;
void hookNewFrameEvent(Action<byte[]> x) {
    decoder.NewFrame -= current;
    decoder.NewFrame += x;
    current = x;
}

Что остается наиболее эффективным решением в этомкритичный ко времени кусок кода.

Ответы [ 2 ]

0 голосов
/ 31 мая 2018

Вы прикрепили событие target из currentNewFrameDelegate к decoder.NewFrame, оно не сохраняет ссылку на вашего делегата, тогда перезапись ничего не изменит.Тем не менее, вы можете удалить старый обработчик событий (здесь я предполагаю, что событие декодера является синхронным):

playingStarted(byte[] image) {
    SomeInitializationTasks();

    processImage(image);
    decoder.NewFrame -= playingStarted;
    decoder.NewFrame += imageReceived;
}

Наконец, сбросьте currentNewFrameDelegate вещь также в ctor:

MyClass() {
    decoder.NewFrame += playingStarted;
}

Обратите внимание, что если по какой-либо причине вам потребуется отслеживать индекс кадра, вы можете использовать только один обработчик событий:

int frameIndex = 0;

playingStarted(byte[] image) {
    if (frameIndex++ == 0)
        SomeInitializationTasks();

    processImage(image);
}
0 голосов
/ 31 мая 2018

Я бы просто использовал флаг:

private bool _isFirstTime = true;

ImageReceived(byte[] image) {
    if(_isFirstTime) {
        playingStarted(image);
        _isFirstTime = false;
    }
    processImage(image);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...