Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/mercurial/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 使用RX创建IO绑定可观测_C#_Multithreading_Asynchronous_Io_System.reactive - Fatal编程技术网

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线程
解决这些问题的一种方法是只使用async Create方法:

// 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();