C# 使用RX创建IO绑定可观测
我有一个工作线程进行阻塞调用(C# 使用RX创建IO绑定可观测,c#,multithreading,asynchronous,io,system.reactive,C#,Multithreading,Asynchronous,Io,System.reactive,我有一个工作线程进行阻塞调用(ReadFrame) 从套接字读取传入数据(IO绑定)。 线程运行一个循环,将数据输入主题, 消费者可以观察到这一点 private void ReadLoop() { while (!IsDisposed) { var frame = _Socket.ReadFrame(); _ReceivedFrames.OnNext(frame); } } 我想知道是否有一种更有效的方法来做到这一点 下面是我的一个尝试
ReadFrame
)
从套接字读取传入数据(IO绑定)。
线程运行一个循环,将数据输入主题
,
消费者可以观察到这一点
private void ReadLoop()
{
while (!IsDisposed)
{
var frame = _Socket.ReadFrame();
_ReceivedFrames.OnNext(frame);
}
}
我想知道是否有一种更有效的方法来做到这一点
下面是我的一个尝试(玩具示例):
我正在努力正确使用ObserveOn
、SubscribeOn
和调度器。
玩具示例似乎有效,但我不确定线程的生命周期是否得到正确管理
读卡器线程是否通过调用d.Dispose()
关闭?我需要创建一个新线程吗?
我是否应该使用
Observable.Create
?怎么做
以下是@Enigmativity要求的其他信息:
ReadLoop()
方法是符合以下接口的类的一部分:
public interface ICanSocket : IDisposable
{
IObservable<CanFrame> ReceivedFrames { get; }
IObserver<CanFrame> FramesToSend { get; }
}
公共接口ICanSocket:IDisposable
{
IObservable接收框架{get;}
IObserver框架发送{get;}
}
当父ICanSocket
被释放时,其成员\u Socket
被释放(关闭)。实现这一点的最“Rxy”方法是使用,它具有执行异步I/O的可观察方法
看来你主要关心的是:
- 订阅时,不要阻止订阅线程(即在后台线程上运行I/O线程)
- 当调用者取消订阅时,停止I/O线程
// just use Task.Run to "background" the work
var src = Observable
.Create<CanFrame>((observer, cancellationToken) => Task.Run(() =>
{
while (!cancellationToken.IsCancellationRequested)
{
var frame = _Socket.ReadFrame();
if (frame == null) // end of stream?
{
// will send a Completed event
return;
}
observer.OnNext(frame);
}
}));
var d = src.Subscribe(s => s.Dump());
Console.ReadLine();
d.Dispose();
//只需使用任务。运行到“后台”工作
var src=可观测
.Create((observer,cancellationToken)=>Task.Run(()=>
{
而(!cancellationToken.IsCancellationRequested)
{
var frame=_Socket.ReadFrame();
if(frame==null)//流结束?
{
//将发送已完成的事件
返回;
}
observer.OnNext(框架);
}
}));
var d=src.Subscribe(s=>s.Dump());
Console.ReadLine();
d、 处置();
您的\u套接字是什么类型的,以及ReadFrame()
是什么样子的?\u套接字是一个包装器<代码>ReadFrame()
调用。我不认为这些细节与手头的(更一般的)问题(IO绑定的生产者)有关。创建可观察对象的方式不是正确的做事方式,但因为它是一个套接字,很难判断是否可观察。创建或可观察。使用将是最好的方法。所以细节是相关的。你能告诉我们如何设置你的项目,以便我们有可编译的代码吗?项目设置很复杂。它包括使用gcc编译一个.c文件,一个使用P/Invoke的c#类,另外它必须在mono/linux上运行。难道我们不能假装ReadFrame()
从慢速磁盘读取数据块吗?我想结果是一样的……不,不是。您需要将状态封装在observable中,observable需要管理套接字的生存期。我们至少需要知道套接字类的签名才能提供帮助。这不是为每个订阅者创建了一个新任务吗?如果为真,订阅者将相互窃取帧。另外,你认为Rxx的哪些方法?是的。如果希望多个观察者共享同一个流,请附加一个.Publish().RefCount()
。我已经有一段时间没有使用Rxx了。查找套接字和流。它有许多方法将这些作为输入并返回可观察的数据。
// just use Task.Run to "background" the work
var src = Observable
.Create<CanFrame>((observer, cancellationToken) => Task.Run(() =>
{
while (!cancellationToken.IsCancellationRequested)
{
var frame = _Socket.ReadFrame();
if (frame == null) // end of stream?
{
// will send a Completed event
return;
}
observer.OnNext(frame);
}
}));
var d = src.Subscribe(s => s.Dump());
Console.ReadLine();
d.Dispose();