Jako część naszej aplikacji (w produkcji przez około 4 miesięcy) mamy strumienia danych pochodzących z zewnętrznego urządzenia, które przekształcają się do IObservablepreferowaną metodą generowania IObservable <String> ze strumienia
Aż teraz używamy następujących po to, aby ją wygenerować i działa ona całkiem dobrze.
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;
}
}
}
Ostatniej nocy zastanawiałem się, czy istnieje sposób, aby użyć składni yield return
aby osiągnąć ten sam wynik i wyszedł z tego:
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;
}
}
}
Wydaje się całkiem dobrze i jest znacznie czystsze, ale zastanawiałem się, czy są jakieś plusy i minusy w jedną stronę, czy w inny sposób.
Pro: 'return' wydajność obsługuje leniwy/późne ładowanie kolekcji. –
Con: kiedy jest wyjątek nie nazywają onException, to po prostu się pęcherzyki –
Myślę, że to zależy, jeśli nie przeszkadza palenie nić zrobić swoją pętlę odczytu, który jedzie w dół, ile urządzeń trzeba wspierać. Napisałem AsyncTextReader, który sam był Observable, aby zrobić coś podobnego, ale na dużą skalę. Z pewnością w tych dniach można było czekać na coś ... –
piers7