我正在使用视频解码器,每次构建一个帧时都会发送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;
}
在这段时间关键的代码中,它仍然是最有效的解决方案。
答案 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);
}