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]

VB.NET Aufbau

Sie verfügen nach der Schulung über fundierte Kenntnisse in der Arbeit mit objektorientierten Modellen in VB.NET und können wiederverwendbare Komponenten eigenständig erzeugen.

ASP.NET 2.0 und 3.5

Dieser Kurs vermittelt Ihnen alle Erweiterungen von Microsoft ASP.NET 2.0. Zu diesen zählen u. a. Data Bindung, Master Pages, und Security.

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!