diff Implab/Components/PollingComponent.cs @ 259:7d52dc684bbd v3

PollingComponent: implemented correct stopping
author cin
date Fri, 13 Apr 2018 03:57:39 +0300
parents d0876436d95d
children 547a2fc0d93e
line wrap: on
line diff
--- a/Implab/Components/PollingComponent.cs	Fri Apr 13 00:44:57 2018 +0300
+++ b/Implab/Components/PollingComponent.cs	Fri Apr 13 03:57:39 2018 +0300
@@ -9,6 +9,9 @@
 
         readonly CancellationTokenSource m_cancellation = new CancellationTokenSource();
 
+        Task m_pending;
+        Task m_poll;
+
         /// <summary>
         /// Poll interval in milliseconds.
         /// </summary>
@@ -41,20 +44,33 @@
         }
 
 
-        //TODO override stop
+        protected override async Task StopInternalAsync(CancellationToken ct) {
+            // component in Stopping state, no new polls will be scheduled
+            m_cancellation.Cancel();
+            try {
+                // await for pending poll
+                await m_poll;
+            } catch (OperationCanceledException e) {
+                // OK
+            }
+        }
         
         protected abstract Task Poll(CancellationToken ct);
 
         void ScheduleNextPoll(int timeout) {
             lock (SynchronizationObject) {
-                if (State == ExecutionState.Running)
+                if (State == ExecutionState.Running) {
+                    m_pending = Safe.CreateTask(m_cancellation.Token);
+                    m_poll = m_pending.Then(() => Poll(m_cancellation.Token));
                     m_timer.Change(timeout, Timeout.Infinite);
+                }
             }
         }
 
-        void OnTimer(object state) {
+        async void OnTimer(object state) {
             try {
-                Poll(m_cancellation.Token);
+                m_pending.Start();
+                await m_poll;
             } catch (Exception e) {
                 UnhandledException.DispatchEvent(this, new UnhandledExceptionEventArgs(e, false));
                 if (FailOnError)