using System; namespace ScheduleWork { public interface IScheduleWork { bool IsRun { get; } bool IsCompleted { get; } bool IsFailed { get; } Exception FailedException { get; } bool IsFailedRollback { get; set; } float Progress { get; } IScheduleWork Start(); IScheduleWork Stop(); IScheduleWork Wait(); void Rollback(); } } using System; using System.Threading; using System.Threading.Tasks; namespace ScheduleWork { public abstract class ScheduleWorkBase : IScheduleWork { private float progress = 0f; public Action<float> UpdateProgressAction; public Action<IScheduleWork> CompletedAction; public virtual object Result { get; protected set; } public bool IsRun { get; private set; } public bool IsCompleted { get; protected set; } public bool IsFailed { get; protected set; } public Exception FailedException { get; protected set; } public bool IsFailedRollback { get; set; } public float Progress { get { return this.progress; } set { if (this.progress != value) { this.progress = value; this.UpdateProgress(); } } } public Task CurrentTask { get; protected set; } public CancellationTokenSource TokenSource { get; protected set; } public ScheduleWorkBase() { this.Progress = 0f; this.IsCompleted = false; this.IsFailed = false; this.IsFailedRollback = true; } public IScheduleWork Start() { return this.Start(null); } public IScheduleWork Start(Action<IScheduleWork> complete) { if (this.IsRun) { throw new InvalidOperationException("IsRun: True"); } this.Progress = 0f; this.IsCompleted = false; this.IsFailed = false; if (complete != null) { this.CompletedAction = (Action<IScheduleWork>)Delegate.Combine(this.CompletedAction, complete); } this.TokenSource = new CancellationTokenSource(); this.CurrentTask = Task.Factory.StartNew(new Action(this.RunWorkingWrapping), this.TokenSource.Token); this.CurrentTask.ContinueWith(new Action<Task>(this.Completed)); return this; } public IScheduleWork Stop() { if (!this.IsRun) { throw new InvalidOperationException("IsRun: False"); } if (this.TokenSource != null) { this.TokenSource.Cancel(); } return this; } public IScheduleWork Wait() { try { this.CurrentTask.Wait(); } catch (Exception ex) { Console.WriteLine(ex.Message); } return this; } public virtual void Rollback() { } protected void RunWorkingWrapping() { try { this.IsRun = true; this.Result = this.RunWorking(); } catch (Exception e) { this.IsFailed = true; this.FailedException = e; if (this.IsFailedRollback) { this.Rollback(); } } finally { this.IsCompleted = true; this.IsRun = false; } } protected abstract object RunWorking(); protected void UpdateProgress() { if (this.UpdateProgressAction != null) { this.UpdateProgressAction(this.Progress); } } protected void Completed(Task t) { if (this.CompletedAction != null) { this.CompletedAction(this); } } } }
using System; using System.Collections.Generic; using System.Linq; namespace ScheduleWork { public class CollectionScheduleWork : ScheduleWorkBase { private IList<ScheduleWorkBase> AllWork; private IList<ScheduleWorkBase> CompletedWork; public override object Result { get { return ( from m in this.CompletedWork select m.Result).ToList<object>(); } protected set { } } public CollectionScheduleWork() { this.AllWork = new List<ScheduleWorkBase>(); this.CompletedWork = new List<ScheduleWorkBase>(); } protected override object RunWorking() { this.CompletedWork.Clear(); foreach (ScheduleWorkBase item in this.AllWork) { item.Start(); item.CurrentTask.Wait(); if (item.IsFailed) { throw item.FailedException; } this.CompletedWork.Add(item); } return ( from c in this.CompletedWork select c.Result).ToList<object>(); } public void AddScheduleWork(ScheduleWorkBase scheduleWork) { if (base.IsRun || base.IsCompleted) { throw new InvalidOperationException("IsRun || IsCompleted"); } this.AllWork.Add(scheduleWork); } public override void Rollback() { Console.WriteLine("CollectionScheduleWork.Rollback"); foreach (ScheduleWorkBase item in this.CompletedWork) { item.Rollback(); } } } }
using System; namespace ScheduleWork { public class DelegateScheduleWork : ScheduleWorkBase { public Func<ScheduleWorkBase, object> ScheduleWorkAction; public Func<ScheduleWorkBase, bool> RollbackAction; public DelegateScheduleWork(Func<ScheduleWorkBase, object> action, Func<ScheduleWorkBase, bool> rollback) { this.ScheduleWorkAction = action; this.RollbackAction = rollback; } public DelegateScheduleWork(Func<ScheduleWorkBase, object> action) : this(action, null) { } protected override object RunWorking() { object result; if (this.ScheduleWorkAction != null) { result = this.ScheduleWorkAction(this); } else { result = null; } return result; } public override void Rollback() { if (this.RollbackAction != null) { this.RollbackAction(this); } } } }
using System; namespace ScheduleWork { public class ScheduleWorkEventArgs : EventArgs { public bool IsCompleted { get { return this.Target.IsCompleted; } } public bool IsFailed { get { return this.Target.IsFailed; } } public IScheduleWork Target { get; private set; } public ScheduleWorkEventArgs(IScheduleWork target) { this.Target = target; } } }