//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;
}
}
}