diff --git a/src/NmeaParser/BufferedStreamDevice.cs b/src/NmeaParser/BufferedStreamDevice.cs index da55a95..8980a7f 100644 --- a/src/NmeaParser/BufferedStreamDevice.cs +++ b/src/NmeaParser/BufferedStreamDevice.cs @@ -61,9 +61,20 @@ namespace NmeaParser var stream = await GetStreamAsync().ConfigureAwait(false); StreamReader sr = new StreamReader(stream); m_stream = new BufferedStream(sr, emulationSettings); + m_stream.EndOfStreamReached += OnEndOfStreamReached; return m_stream; } + private void OnEndOfStreamReached(object sender, EventArgs e) + { + EndOfStreamReached?.Invoke(this, e); + if (m_stream is BufferedStream stream && !stream.CanRewind && IsOpen) + { + // If we can't rewind the stream, stop + _ = CloseAsync(); + } + } + /// /// Gets or sets the emulated baud rate. Defaults to 115200 /// @@ -107,7 +118,11 @@ namespace NmeaParser /// protected override Task CloseStreamAsync(System.IO.Stream stream) { - m_stream?.Dispose(); + if (m_stream != null) + { + m_stream.EndOfStreamReached -= OnEndOfStreamReached; + m_stream?.Dispose(); + } return Task.FromResult(true); } @@ -134,6 +149,11 @@ namespace NmeaParser EmptyLine } + /// + /// Raised when the stream has reached the end. If the stream can be revound, it'll start over, unless you stop the device in this thread. + /// + public event EventHandler? EndOfStreamReached; + // stream that slowly populates a buffer from a StreamReader to simulate nmea messages coming // in lastLineRead by lastLineRead at a steady stream private class BufferedStream : Stream @@ -159,6 +179,8 @@ namespace NmeaParser m_readTask = StartReadLoop(m_tcs.Token); } + internal bool CanRewind => m_sr.BaseStream.CanSeek; + private async Task StartReadLoop(CancellationToken cancellationToken) { await Task.Yield(); @@ -230,7 +252,12 @@ namespace NmeaParser if (m_tcs.IsCancellationRequested) return null; if (m_sr.EndOfStream) + { + EndOfStreamReached?.Invoke(this, EventArgs.Empty); + if (m_tcs.IsCancellationRequested) + return null; m_sr.BaseStream.Seek(0, SeekOrigin.Begin); //start over + } return m_sr.ReadLine() + '\n'; } @@ -295,6 +322,8 @@ namespace NmeaParser m_sr.Dispose(); base.Dispose(disposing); } + + internal event EventHandler? EndOfStreamReached; } } }