view Implab/Components/PollingComponent.cs @ 258:d0876436d95d v3

missing file
author cin
date Fri, 13 Apr 2018 00:44:57 +0300
parents
children 7d52dc684bbd
line wrap: on
line source

using System;
using System.Threading;
using System.Threading.Tasks;

namespace Implab.Components {
    public abstract class PollingComponent : RunnableComponent {

        readonly Timer m_timer;

        readonly CancellationTokenSource m_cancellation = new CancellationTokenSource();

        /// <summary>
        /// Poll interval in milliseconds.
        /// </summary>
        /// <returns></returns>
        public int Interval { get; set; }

        /// <summary>
        /// Delay to the first poll after start in milliseconds
        /// </summary>
        /// <returns></returns>
        public int Delay { get; set; }

        /// <summary>
        /// Indicates how to handle unhandled exceptions in <see cref="Poll()"/> method.
        /// </summary>
        /// <returns></returns>
        public bool FailOnError { get; set; }

        /// <summary>
        /// Event for the unhandled exceptions in <see cref="Poll()"/> method.
        /// </summary>
        public event EventHandler<UnhandledExceptionEventArgs> UnhandledException;

        protected PollingComponent(bool initialized) : base(initialized) {
            m_timer = new Timer(OnTimer);
        }

        protected override void RunInternal() {
            ScheduleNextPoll(Delay);
        }


        //TODO override stop
        
        protected abstract Task Poll(CancellationToken ct);

        void ScheduleNextPoll(int timeout) {
            lock (SynchronizationObject) {
                if (State == ExecutionState.Running)
                    m_timer.Change(timeout, Timeout.Infinite);
            }
        }

        void OnTimer(object state) {
            try {
                Poll(m_cancellation.Token);
            } catch (Exception e) {
                UnhandledException.DispatchEvent(this, new UnhandledExceptionEventArgs(e, false));
                if (FailOnError)
                    Fail(e);
            }
            ScheduleNextPoll(Interval);
        }

        protected override void Dispose(bool disposing) {
            if (disposing)
                Safe.Dispose(m_timer, m_cancellation);
            base.Dispose(disposing);
        }

    }
}