Feedback

C# - Wiederkehrende Tasks

Veröffentlicht von am 09.11.2015
(2 Bewertungen)
Basisklasse für die Implementierung von wiederkehrenden Tasks während der Programm Ausführung.
Hierbei wird auf Threads, BackgroundWorker und Timer Objekte verzichtet.

Beispiel Program:
namespace Snippets.Net
{
using System;
using System.Collections.Generic;

class ExampleProgram
{
static void Main(string[] args)
{
var jobs = new List<ISchedulerJob>();
jobs.Add(new SchedulerJobA());
jobs.Add(new SchedulerJobB());

jobs.ForEach(x => x.Start());

Console.ReadLine();

jobs.ForEach(x => x.Stop());
}
}

public class SchedulerJobA : SchedulerJobBase
{
protected override void OnDispose()
{
}

protected override void OnExecution()
{
WriteToConsole($"{ GetType().Name} Warning");
}

protected override void OnInstanceCreated()
{
Delay = TimeSpan.FromSeconds(8);
Interval = TimeSpan.FromSeconds(16);
}
}

public class SchedulerJobB : SchedulerJobBase
{
protected override void OnDispose()
{
}

protected override void OnExecution()
{
WriteToConsole($"{GetType().Name} Information");
}

protected override void OnInstanceCreated()
{
Delay = TimeSpan.FromSeconds(5);
Interval = TimeSpan.FromSeconds(3);
}
}
}


Beispiel Ausgabe:
[13:50:18] Scheduler Job 'SchedulerJobA' started. Recurring every 16 seconds, after a delay of 00:00:07.9927205.
[13:50:18] Scheduler Job 'SchedulerJobB' started. Recurring every 03 seconds, after a delay of 00:00:04.9834796.
[13:50:23] SchedulerJobB - Calling OnExecution Method
[13:50:23] SchedulerJobB Information
[13:50:26] SchedulerJobB - Calling OnExecution Method
[13:50:26] SchedulerJobA - Calling OnExecution Method
[13:50:26] SchedulerJobB Information
[13:50:26] SchedulerJobA Warning
[13:50:29] SchedulerJobB - Calling OnExecution Method
[13:50:29] SchedulerJobB Information
[13:50:32] SchedulerJobB - Calling OnExecution Method
[13:50:32] SchedulerJobB Information
[13:50:35] SchedulerJobB - Calling OnExecution Method
[13:50:35] SchedulerJobB Information
[13:50:38] SchedulerJobB - Calling OnExecution Method
[13:50:38] SchedulerJobB Information
[13:50:41] SchedulerJobB - Calling OnExecution Method
[13:50:41] SchedulerJobB Information
[13:50:42] SchedulerJobA - Calling OnExecution Method
[13:50:42] SchedulerJobA Warning
[13:50:44] SchedulerJobB - Calling OnExecution Method
[13:50:44] SchedulerJobB Information
[13:50:47] SchedulerJobB - Calling OnExecution Method
[13:50:47] SchedulerJobB Information
GFU-Schulungen  [Anzeige]

C# Grundlagen

Die Schulung vermittelt Ihnen die Grundlagen von C# in der Arbeit mit Datentypen sowie bei Klassenbibliotheken. Sie lernen, mit Variablen umzugehen und deren verschiedene Formen zu konvertieren. 

XML und .NET Überblick

Um auf dem neuesten Wissensstand zu sein, sollten Sie unser aktuelles ASP .NET Komplett Seminar belegen.
Nach dem Seminar kennen Sie die wichtigsten Strömungen in der Software-Technologie

namespace Snippets.Net
{
    using System;
    using System.Diagnostics;
    using System.Threading;
    using System.Threading.Tasks;

    public interface ISchedulerJob : IDisposable
    {
        CancellationTokenSource CancellationTokenSource { get; }

        TimeSpan? Delay { get; set; }
        DateTime? EndTime { get; set; }
        TimeSpan Interval { get; set; }
        DateTime? StartTime { get; set; }

        bool IsActive { get; }

        void Start();
        void Stop();
    }

    public abstract class SchedulerJobBase : ISchedulerJob
    {
        #region Fields
        private bool _disposed = false;

        private CancellationTokenSource _tokenSource;

        private DateTime? _startTime;
        private DateTime? _endTime;

        private bool _isActive;
        private TimeSpan _interval;

        private readonly Stopwatch _stopWatch;
        #endregion

        #region Properties
        public CancellationTokenSource CancellationTokenSource => _tokenSource;

        public TimeSpan? Delay
        {
            get
            {
                if (!_startTime.HasValue) return null;
                return _startTime.Value - DateTime.Now;
            }

            set
            {
                if (value.HasValue) _startTime = DateTime.Now.Add(value.Value);
            }
        }

        public DateTime? EndTime
        {
            get
            {
                return _endTime;
            }

            set
            {
                _endTime = value;
            }
        }

        public TimeSpan Interval
        {
            get
            {
                return _interval;
            }

            set
            {
                _interval = value;
            }
        }

        public bool IsActive => _isActive;

        public DateTime? StartTime
        {
            get
            {
                return _startTime;
            }

            set
            {
                _startTime = value;
            }
        }
        #endregion

        #region Constructor
        protected SchedulerJobBase() : base()
        {
            OnInstanceCreated();

            _tokenSource = new CancellationTokenSource();
            _isActive = false;
            _stopWatch = new Stopwatch();
        }
        #endregion

        #region Methods
        public async void Start()
        {
            if (_isActive) return;

            WriteToConsole($"Scheduler Job '{GetType().Name}' started. Recurring every {Interval:ss} seconds, after a delay of {Delay}.");
            _isActive = true;
            var currentDelay = TimeSpan.Zero;
            if (_startTime.HasValue) currentDelay = _startTime.Value - DateTime.Now;
            if (currentDelay <= TimeSpan.Zero) currentDelay = TimeSpan.Zero;

            await Task.Delay(currentDelay, _tokenSource.Token);

            TimeSpan newInterval;

            while ((!_tokenSource.IsCancellationRequested))
            {
                _stopWatch.Restart();
                try
                {
                    WriteToConsole($"{GetType().Name} - Calling OnExecution Method");
                    await Task.Run(new Action(OnExecution), _tokenSource.Token);
                }
                catch (Exception ex)
                {
                    WriteToConsole($"Error - {GetType().Name}");
                    WriteToConsole(ex.ToString());
                }
                finally
                {
                    _stopWatch.Stop();
                }

                newInterval = _interval - _stopWatch.Elapsed;
                if (newInterval < TimeSpan.Zero) newInterval = _interval;

                if (_endTime.HasValue && _endTime.Value < DateTime.Now) Stop();
                await Task.Delay(newInterval, _tokenSource.Token);
            }
        }

        public void Stop()
        {
            if (!_isActive) return;
            Console.WriteLine($"{GetType().Name} stopped");
            _tokenSource.Cancel();
            _isActive = false;
        }

        protected abstract void OnInstanceCreated();

        protected abstract void OnExecution();

        protected abstract void OnDispose();

        protected void WriteToConsole(string message)
        {
            Console.WriteLine($"[{DateTime.Now:HH:mm:ss}] " + message);
        }
        #endregion

        #region IDisposable Support
        protected virtual void Dispose(bool disposing)
        {
            if (!_disposed)
            {
                if (disposing)
                {
                    _tokenSource?.Dispose();
                    OnDispose();
                }
                _disposed = true;
            }
        }

        void IDisposable.Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }
        #endregion
    }
}

Kommentare zum Snippet

 

Logge dich ein, um hier zu kommentieren!