代码之家  ›  专栏  ›  技术社区  ›  Larry

切换事件委托

  •  1
  • Larry  · 技术社区  · 6 年前

    我在用一个视频解码器 NewFrame 每次生成帧时的事件。

    因为我需要在它第一次运行时完成一些初始化任务,所以我需要使用hook this frame event到 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);
    }
    

    不幸的是,听起来不是这样的…这个 开始播放 函数仍然在每次 新框架 收到。

    因为我还有几个地方想把这个代表换回去 开始播放 ,我不想使用-=then+=hack来阻止多个事件订阅,因为它使代码可读性降低。

    如何这样切换事件委托?


    编辑:

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

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

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

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

    2 回复  |  直到 6 年前
        1
  •  1
  •   Adriano Repetti    6 年前

    你附加了 目标 属于 currentNewFrameDelegate decoder.NewFrame 事件,它不保留对委托的引用,则重写不会更改任何内容。但是,您可以删除 古老的 事件处理程序(这里我假设解码器事件是同步的):

    playingStarted(byte[] image) {
        SomeInitializationTasks();
    
        processImage(image);
        decoder.NewFrame -= playingStarted;
        decoder.NewFrame += imageReceived;
    }
    

    终于放下了 当前新框架委托 还有一件事在CTR中:

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

    请注意,如果出于任何原因,您需要跟踪帧索引,则可以仅使用一个事件处理程序:

    int frameIndex = 0;
    
    playingStarted(byte[] image) {
        if (frameIndex++ == 0)
            SomeInitializationTasks();
    
        processImage(image);
    }
    
        2
  •  1
  •   Zohar Peled    6 年前

    我只需要使用一个标志:

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