I have a worker thread making blocking calls ( ReadFrame
) to read incoming data from a socket (IO bound). The thread runs a loop, that feeds the data into an Subject
, that can be observed by consumers.
private void ReadLoop()
{
while (!IsDisposed)
{
var frame = _Socket.ReadFrame();
_ReceivedFrames.OnNext(frame);
}
}
I wonder if there is a more RX kind of way to do this.
Here is an attempt (toy example) I made:
var src = Observable
.Repeat(Unit.Default)
.Select(_ =>
{
Thread.Sleep(1000); // simulated blocking ReadFrame call
return "data read from socket";
})
.SubscribeOn(ThreadPoolScheduler.Instance) // avoid blocking when subscribing
.ObserveOn(NewThreadScheduler.Default) // spin up new thread (?)
.Publish()
.RefCount();
var d = src.Subscribe(s => s.Dump()); // simulated consumer
Console.ReadLine(); // simulated main running code
d.Dispose(); // tear down
I'm struggling with the correct use of ObserveOn
, SubscribeOn
and the schedulers. The toy example seems to work, but I'm not sure if the thread's lifetime is managed correctly.
Is the reader thread shut down with the d.Dispose()
call?
Do I need to create a new thread at all?
Should I use Observable.Create
instead? How?
Below additional info requested by @Enigmativity:
The ReadLoop()
method is part of a class that conforms to the following interface:
public interface ICanSocket : IDisposable
{
IObservable<CanFrame> ReceivedFrames { get; }
IObserver<CanFrame> FramesToSend { get; }
}
Its member _Socket
is disposed (closed) when the parent ICanSocket
is disposed.
The most "Rxy" way to do this is to use Rxx , which has observable methods for doing async I/O.
Seems like your primary concerns are:
One way to solve these is to just use the async Create method:
// 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();
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.