Come parte di applicazione (in produzione per circa 4 mesi) abbiamo un flusso di dati provenienti da un dispositivo esterno che si convertono ad un IObservablemetodo preferito per generare un IObservable <String> da un flusso
Fino ora abbiamo usato il seguente per generarlo, e ha funzionato abbastanza bene.
IObservable<string> ObserveStringStream(Stream inputStream)
{
var streamReader = new StreamReader(inputStream);
return Observable
.Create<string>(observer => Scheduler.ThreadPool
.Schedule(() => ReadLoop(streamReader, observer)));
}
private void ReadLoop(StreamReader reader, IObserver<string> observer)
{
while (true)
{
try
{
var line = reader.ReadLine();
if (line != null)
{
observer.OnNext(line);
}
else
{
observer.OnCompleted();
break;
}
}
catch (Exception ex)
{
observer.OnError(ex);
break;
}
}
}
Ieri sera mi sono chiesto se ci fosse un modo per utilizzare la sintassi yield return
per ottenere lo stesso risultato e si avvicinò con questo:
IObservable<string> ObserveStringStream(Stream inputStream)
{
var streamReader = new StreamReader(inputStream);
return ReadLoop(streamReader)
.ToObservable(Scheduler.ThreadPool);
}
private IEnumerable<string> ReadLoop(StreamReader reader)
{
while (true)
{
var line = reader.ReadLine();
if (line != null)
{
yield return line;
}
else
{
yield break;
}
}
}
Sembra funzionare abbastanza bene ed è molto più pulito, ma mi stavo chiedendo se ci fossero pro o contro per un modo rispetto all'altro, o se ci fosse un modo migliore del tutto.
Pro: 'return' rendimento supporta lazy loading/fine della vostra collezione. –
Con: quando viene generata un'eccezione non chiama OnException, si bolle solo su –
Immagino che dipende se non ti dispiace la masterizzazione di un thread per eseguire il ciclo di lettura, che scende a quanti dispositivi è necessario supportare. Ho scritto un AsyncTextReader che era a sua volta Osservabile per fare qualcosa di simile, ma in scala. Sicuramente in questi giorni si potrebbe ATTENDERE qualcosa ... –
piers7