切换事件委托

时间:2018-05-31 08:15:57

标签: c# events delegates

我正在使用视频解码器,每次构建一个帧时都会发送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 + = hack来阻止多个事件订阅,因为它会降低代码的可读性。< / p>

如何以这种方式切换事件委托?

修改

这可以通过这种方式实现:

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

然而,每次事件被触发时它都会创建一个双重调用...所以我很遗憾地写了这个:

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

在这段时间关键的代码中,它仍然是最有效的解决方案。

2 个答案:

答案 0 :(得分:1)

我只想使用一个标志:

private bool _isFirstTime = true;

ImageReceived(byte[] image) {
    if(_isFirstTime) {
        playingStarted(image);
        _isFirstTime = false;
    }
    processImage(image);
}

答案 1 :(得分:1)

您将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);
}