c# - 如何为遗留相机系统创建 Observable?
问题描述
我有一个旧的相机客户端来与相机通信。它的工作方式在当时有点尴尬。作为我自己的“反应式”东西的粉丝,我想以反应式的方式与相机交流。
它是这样运作的
每当您想开始捕获帧时,您调用Start并开始每 0.5 秒捕获一个帧,并且您会在订阅“on capture”事件的每个帧上收到通知。该事件一直在引发,直到您调用Stop为止。
因此,相机具有:
- 开始捕获帧的方法
- 另一种停止捕获的方法
- 捕获新帧时引发的事件
这就是我要的
我想将相机封装成一个更方便的抽象,其中 Start 和 Stop 方法被替换为 anIObservable<bool>
并且生成的 observable 应该发出批量捕获(Frames
)。
更多细节
这是传统的相机类:
class Camera
{
void StartRecording();
void StopRecording();
public event CaptureEventHandler OnCapture;
public delegate void CaptureEventHandler(Camera sender, Frame capture);
}
我想要的是创建将相机包装成这样的类(我只创建了骨架):
public class ObservableCamera
{
public ObservableCamera(Camera camera, IObservable<bool> enableCapture)
{
// TODO: Define the 'Captures' observable using the parameters above
}
IObservable<Frame[]> Captures { get; }
}
当 enableCapture 可观察对象发出 a 时,相机应该开始捕捉帧,true
并且在它按下时应该停止捕捉false
。
为了澄清一点,这是显示交互的大理石图:
- 第一个序列是
enableCapture
- 第二个应该是从
OnCapture
事件创建的辅助序列。
除此之外,无论何时启动 Start操作,也应在可观察对象终止或失败StopRecording
时调用。enableCapture
那么,我要问什么?
我收到评论说我的目标不明确。为了澄清它,这是我的问题:
我应该如何实现 observable 来处理旧相机?我不知道如何开始。
解决方案
这是一种方法,它使用Window
运算符来定义启用相机时的窗口(周期)。该Camera.OnCapture
事件在每个窗口开始时被订阅,在窗口结束时被取消订阅。
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
运算符用于忽略连续的真或假。使用Publish
运算符是为了避免多次订阅该enableCapture
序列。这个序列很可能是一个Subject<bool>
,所以已经很热了,这使得它Publish
本质上是多余的,但原则上避免多个订阅是好的。
没有注意该方法StartRecording
或该StopRecording
方法失败的情况。在这种情况下,对该事件的订阅OnCapture
将被泄露。
推荐阅读
- html - 设置为无时重复背景图像
- c# - 如何在 blazor 中获取单选按钮的值?
- python - pyspark 使用通用键集添加值(python)
- html - 保持 div 垂直对齐,并且它们的内容不会重叠
- javascript - 关于元素对齐的问题以及光标如何与此可编辑代码文本区域中的文本保持齐平?
- c - 从 C 中的文件 .txt 创建树
- email - Google Apps Script_根据 google 表单数据填充多个模板,然后通过电子邮件发送 pdf 副本
- vue.js - 是否可以在 Vue 中为 Web 应用程序中的所有输入绑定焦点事件?
- javascript - 如何使用 vuex 自动刷新帖子列表?
- node.js - 未找到条带签名:Express 中间件问题