From d998b65a9cfacb802052f6c602311243404f5f1e Mon Sep 17 00:00:00 2001 From: Mark van Renswoude Date: Thu, 13 Aug 2020 11:24:17 +0200 Subject: [PATCH] Attempt at making the connection more robust --- CameraStream.cs | 46 ++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 44 insertions(+), 2 deletions(-) diff --git a/CameraStream.cs b/CameraStream.cs index c730e67..2c1b8fd 100644 --- a/CameraStream.cs +++ b/CameraStream.cs @@ -29,7 +29,7 @@ namespace IPCamAppBar private readonly CancellationTokenSource cancelTaskTokenSource = new CancellationTokenSource(); private Task streamTask; - + private DataMonitor dataMonitor; protected CameraStream() { @@ -89,12 +89,24 @@ namespace IPCamAppBar cancellationToken.ThrowIfCancellationRequested(); } + if (response.StatusCode != HttpStatusCode.OK) throw new WebException(response.StatusDescription); using (var responseStream = response.GetResponseStream()) { - await ReadFrames(responseStream, cancellationToken); + var dataMonitorCancellationTokenSource = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken); + dataMonitor = new DataMonitor(dataMonitorCancellationTokenSource, TimeSpan.FromSeconds(15)); + + try + { + await ReadFrames(responseStream, dataMonitorCancellationTokenSource.Token); + } + catch (TaskCanceledException) + { + if (!dataMonitorCancellationTokenSource.IsCancellationRequested) + throw; + } } } catch (TaskCanceledException) @@ -121,6 +133,7 @@ namespace IPCamAppBar protected virtual void OnFrame(FrameEventArgs args) { + dataMonitor.Reset(); Frame?.Invoke(this, args); } @@ -156,6 +169,35 @@ namespace IPCamAppBar return -1; } + } + + internal class DataMonitor + { + private readonly CancellationTokenSource cancellationTokenSource; + private readonly long timeout; + + private readonly Timer timeoutTimer; + + + public DataMonitor(CancellationTokenSource cancellationTokenSource, TimeSpan timeout) + { + this.cancellationTokenSource = cancellationTokenSource; + this.timeout = (long)timeout.TotalMilliseconds; + + timeoutTimer = new Timer(Tick, null, this.timeout, -1); + } + + + public void Reset() + { + timeoutTimer.Change(timeout, -1); + } + + + private void Tick(object state) + { + cancellationTokenSource.Cancel(); + } } }