using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; using System.Threading.Tasks.Dataflow; namespace Sony.Filtr.Tasks.Helpers { public class ProgressTracker { private readonly ConcurrentBag items; private readonly ActionBlock ProcessBlock; private int CurrentProgress = 0; public readonly int Total; public class ProgressItem { public static readonly ProgressItem Empty = new ProgressItem(0, DateTime.Now); public readonly DateTime DT; public readonly int Current; public ProgressItem(int current, DateTime dt) { this.Current = current; this.DT = dt; } public string ToPercentage(int total) { return $"{((double)this.Current / total * 100).ToString("0.00")}%"; } public double HourlyProcessingSpeed(DateTime startTime) { if ((this.DT - startTime).TotalSeconds < 2) { return this.Current; } return (double)this.Current / (this.DT - startTime).TotalSeconds * 3600; } public double HourShift(DateTime startTime) { return (this.DT - startTime).TotalHours; } } public ProgressTracker(int total) { this.items = new ConcurrentBag(); this.ProcessBlock = new ActionBlock( delta => this.items.Add(new ProgressItem(Interlocked.Add(ref this.CurrentProgress, delta), DateTime.Now)), new ExecutionDataflowBlockOptions() { MaxDegreeOfParallelism = 1, EnsureOrdered = true }); this.Total = total; } public int GetCurrentProgress() { return this.CurrentProgress; } public IEnumerable Items { get { return this.items.ToArray(); } } public async Task NextAsync(int delta) { await this.ProcessBlock.SendAsync(delta); } public void Next(int delta, DateTime dt) { this.items.Add(new ProgressItem(Interlocked.Add(ref this.CurrentProgress, delta), dt)); } } }