如何为遗留相机系统创建 Observable?

How to create Observable for a legacy camera system?

我有一个旧相机客户端可以与相机通信。它的工作方式在这个时代有点尴尬。作为我自己的“反应式”东西的粉丝,我想以一种反应式的方式与相机交流。

这是它的运作方式

每当你想开始捕获帧时,你调用 Start 它开始每 0.5 秒捕获一个帧,你会收到订阅“捕获时”事件的每一帧的通知.在您调用 Stop.

之前,该事件会一直发生

因此,相机具有:

这就是我想要的

我想将相机封装到一个更方便的抽象中,其中 Start 和 Stop 方法被替换为 IObservable<bool>,并且生成的 observable 应该发出批量捕获 (Frames)。

更多详情

这是旧相机 class:

class Camera 
{
    void StartRecording();
    void StopRecording();
    public event CaptureEventHandler OnCapture;
    public delegate void CaptureEventHandler(Camera sender, Frame capture);
}

我想要的是像这样将相机包裹成class(我只创建了骨架):

public class ObservableCamera 
{
      public ObservableCamera(Camera camera, IObservable<bool> enableCapture)
      { 
          // TODO: Define the 'Captures' observable using the parameters above
      }

      IObservable<Frame[]> Captures { get; }
}

相机应该在 enableCapture observable 发出 true 时开始捕获帧,并在它按下 false 时停止捕获。

为了澄清一点,这是显示交互的弹珠图:

除此之外,只要 Start 操作开始,enableCapture observable 终止或失败时也应调用 StopRecording

那么,我要求什么?

我收到评论说我的目标不明确。澄清一下,这是我的问题:

我应该如何实现 observable 来处理遗留相机?我不知道如何开始。

这是一种方法,它使用 Window 运算符来定义启用相机时的 windows(周期)。 Camera.OnCapture 事件在每个 window 开始时订阅,并在 window 结束时取消订阅。

Camera camera;
IObservable<bool> enableCapture;

IObservable<Frame[]> observableCamera = enableCapture
    .DistinctUntilChanged()
    .Publish(published => published
        .Window(published.Where(enabled => enabled), _ => published.Where(enabled => !enabled))
        .Select(w =>
            Observable
                .FromEvent<Camera.CaptureEventHandler, Frame>(
                    h => (sender, capture) => h(capture),
                    h =>
                    {
                        camera.OnCapture += h;
                        camera.StartRecording();
                    },
                    h =>
                    {
                        camera.StopRecording();
                        camera.OnCapture -= h;
                    })
                .TakeUntil(w.LastOrDefaultAsync())
                .ToArray()
        )
        .Concat()
    );

DistinctUntilChanged 运算符用于忽略连续的 true 或 false。使用 Publish 运算符是为了避免对 enableCapture 序列进行多次订阅。这个序列很可能是 Subject<bool>,所以已经很热了,使得 Publish 本质上是多余的,但原则上最好避免多次订阅。

未考虑 StartRecordingStopRecording 方法失败的情况。在这种情况下,对 OnCapture 事件的订阅将被泄露。