wasSharp – Rev 20

Subversion Repositories:
Rev:
///////////////////////////////////////////////////////////////////////////
//  Copyright (C) Wizardry and Steamworks 2013 - License: GNU GPLv3      //
//  Please see: http://www.gnu.org/licenses/gpl.html for legal details,  //
//  rights of fair usage, the disclaimer and warranty conditions.        //
///////////////////////////////////////////////////////////////////////////

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

namespace wasSharp.Timers
{
    public class Timer : IDisposable
    {
        private readonly Action callback;
        private readonly Task CompletedTask = Task.FromResult(false);
        private Task Delay;
        private bool Disposed;
        private TimeSpan dueTime;
        private TimeSpan period;
        private CancellationTokenSource tokenSource;

        public Timer(Action callback, TimeSpan dueTime, TimeSpan period)
        {
            this.callback = callback;
            this.dueTime = dueTime;
            this.period = period;

            Run();
        }

        public Timer(Action callback, int dueTime, int period)
            : this(callback, TimeSpan.FromMilliseconds(dueTime), TimeSpan.FromMilliseconds(period))
        {
        }

        public Timer(Action callback) : this(callback, TimeSpan.Zero, TimeSpan.Zero)
        {
        }

        public Timer(Action callback, double dueTime, int period)
            : this(callback, TimeSpan.FromMilliseconds(dueTime), TimeSpan.FromMilliseconds(period))
        {
        }

        public Timer(Action callback, uint dueTime, uint period)
            : this(callback, TimeSpan.FromMilliseconds(dueTime), TimeSpan.FromMilliseconds(period))
        {
        }

        public void Dispose()
        {
            if (tokenSource != null)
            {
                tokenSource.Cancel();
                tokenSource.Dispose();
                tokenSource = null;
            }
            Disposed = true;
        }

        private void Run()
        {
            // Cancel any previous timer.
            if (tokenSource != null)
            {
                tokenSource.Cancel();
                tokenSource.Dispose();
                tokenSource = null;
            }

            // Create a new cancellation source.
            tokenSource = new CancellationTokenSource();

            Action tick = null;
            tick = () =>
            {
                Task.Run(() => callback(), tokenSource.Token);
                if (Disposed)
                    return;
                Delay = !period.Equals(0) ? Task.Delay(period, tokenSource.Token) : CompletedTask;
                if (Delay.IsCompleted)
                    return;
                Delay.ContinueWith(t => tick(), tokenSource.Token);
            };

            Delay = !dueTime.Equals(0) ? Task.Delay(dueTime, tokenSource.Token) : CompletedTask;
            if (Delay.IsCompleted)
                return;
            Delay.ContinueWith(t => tick(), tokenSource.Token);
        }

        public void Change(int dueTime, int period)
        {
            Change(TimeSpan.FromMilliseconds(dueTime), TimeSpan.FromMilliseconds(period));
        }

        public void Change(uint dueTime, int period)
        {
            Change(TimeSpan.FromMilliseconds(dueTime), TimeSpan.FromMilliseconds(period));
        }

        public void Change(TimeSpan dueTime, TimeSpan period)
        {
            this.dueTime = dueTime;
            this.period = period;

            Run();
        }

        public void Stop()
        {
            Change(0, 0);
        }
    }
}

Generated by GNU Enscript 1.6.5.90.