8 Kasım 2018

Arka Planda Sürekli Çalışan İş Örneği

//JobTask.cs

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

namespace TaskJobCreater
{
    public class JobTask
    {
        CancellationTokenSource cancellationTokenSource { get; set; }
        Task task;
        private Task CreateTask(Action action, CancellationToken cancellationToken)
        {
            return new Task(() =>
            {

                while (!cancellationTokenSource.Token.IsCancellationRequested)
                {
                    if (StartDate < DateTime.Now)
                    {
                        IsStarted = true;
                        Started.Invoke(this);
                        action();
                        Completed();
                        return;
                    }
                    task.Wait(1000);
                }
            },
           cancellationTokenSource.Token
           );
        }
        public DateTime StartDate { get; private set; }
        public void Start(DateTime startDate, Action action)
        {            
            if (IsActive)
                throw new InvalidOperationException("Task started before");
            StartDate = startDate;
            cancellationTokenSource = new CancellationTokenSource();

            task = CreateTask(action, cancellationTokenSource.Token);            
            task.Start();
            IsActive = true;
            if (Activated != null)
                Activated.Invoke(this);
        }
        public event Action<object> Stopped;
        public event Action<object> Started;
        public event Action<object> Activated;
        private void Completed()
        {
            
            IsActive = false;
            IsStarted = false;
            Stopped.Invoke(this);
        }
        public void Stop()
        {
            if (IsActive)
            {
                cancellationTokenSource.Cancel();
                try
                {
                    task.Wait();
                }
                catch (OperationCanceledException ce)
                {
                    task.Dispose();
                }
                Completed();
            }
        }
        public bool IsActive { get; private set; }
        public bool IsStarted { get; private set; }

    }
}


/****************************************************************/

//MainWindowModel.cs

using System;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Windows.Input;

namespace TaskJobCreater
{
    public class MainWindowModel : INotifyPropertyChanged
    {
        public MainWindowModel()
        {
            job.Stopped += (s) =>
            {
                Log("Job has ben stopped");
                StartJob();
            };
            job.Started += (s) =>
            {
                Log($"Job has been started");
                ButtonName = "START";
            };
            job.Activated += (s) =>
            {
                Log( $"Job will start after {Convert.ToInt32((job.StartDate - DateTime.Now).TotalSeconds)} seconds later.");
                ButtonName = "STOP";
            };
            StartJob();
            canExecute = true;
        }
        private bool canExecute;
        private ICommand clickCommand;
        public ICommand ClickCommand => clickCommand ?? (clickCommand = new CommandHandler(() => ToogleJob(), canExecute));


        public void ToogleJob()
        {
            if (job.IsActive)
                StopJob();
            else StartJob();
        }
        private void Log(string log)
        {
            Logs += log;
            Logs += Environment.NewLine;
        }
        private void StartJob() => job.Start(DateTime.Now.AddSeconds(5), Job);

        private void StopJob() => job.Stop();

        public void Job() => Log(DateTime.Now.ToString("HH:mm:ss"));




        string m_ButtonName = "START";

        public string ButtonName {
            get { return m_ButtonName; }
            set {
                m_ButtonName = value;
                OnPropertyChanged();
            }
        }

        string m_Logs;

        public string Logs {
            get { return m_Logs; }
            set {
                m_Logs = value;
                OnPropertyChanged();
            }
        }



        public JobTask job = new JobTask();




        #region INotifyPropertyChanged Members

        public event PropertyChangedEventHandler PropertyChanged;

        protected void OnPropertyChanged([CallerMemberName]string propertyName = "")
        {
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }

        #endregion
    }
}


/****************************************************************/

//CommandHandler.cs

using System;
using System.Windows.Input;

namespace TaskJobCreater
{
    public class CommandHandler : ICommand
    {
        private Action action;
        private bool canExecute;

        public CommandHandler(Action action, bool canExecute)
        {
            this.action = action;
            this.canExecute = canExecute;
        }

        public bool CanExecute(object parameter) => canExecute;

        public event EventHandler CanExecuteChanged;

        public void Execute(object parameter) => action();

    }
}
/****************************************************************/

//MainWindow.xaml

<Window x:Class="TaskJobCreater.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:TaskJobCreater"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="auto"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>
        <Button Content="{Binding ButtonName}" Height="40" Command="{Binding ClickCommand}"/>
        <TextBox Grid.Row="1" Text="{Binding Logs}" AcceptsReturn="True"  />
    </Grid>
</Window>

/****************************************************************/
//MainWindow.cs

using System.Windows;

namespace TaskJobCreater
{
    /// 
    /// Interaction logic for MainWindow.xaml
    /// 
    public partial class MainWindow : Window
    {
        public readonly MainWindowModel model;
        public MainWindow()
        {
            InitializeComponent();
            model = new MainWindowModel();
            DataContext = model;
        }
    }
}