Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using System;
- using System.Collections.Concurrent;
- using System.Collections.Generic;
- using System.Linq;
- using System.Threading;
- using System.Threading.Tasks;
- namespace WorkflowTests
- {
- class Program
- {
- static void Main(string[] args)
- {
- Magic magic = new Magic();
- magic.GenerateQueue(100);
- magic.Work(8).Wait(10000);
- magic.Cancel();
- Console.ReadLine();
- }
- }
- class Magic
- {
- CancellationTokenSource tokenSource = new CancellationTokenSource();
- public ConcurrentQueue<Work> workQueue = new ConcurrentQueue<Work>();
- public List<Task> tasks = new List<Task>();
- public void GenerateQueue(int length)
- {
- foreach (int i in Enumerable.Range(0, length))
- {
- if(i % 2 != 0)
- workQueue.Enqueue(new Work1() { ExecuteAt = DateTime.Now.AddSeconds(i) });
- else
- workQueue.Enqueue(new Work2() { ExecuteAt = DateTime.Now.AddSeconds(i) });
- }
- }
- public Task Work(int DOP)
- {
- foreach (int i in Enumerable.Range(1, DOP))
- {
- // pseudo context per worker
- string context = ((char)(i + 64)).ToString();
- // create workers and run them
- tasks.Add(new Worker(context, workQueue, tokenSource.Token).Start());
- }
- return Task.WhenAll(tasks).ContinueWith(Completed);
- }
- public void Cancel()
- {
- Console.WriteLine("Cancel requested");
- tokenSource.Cancel();
- }
- public void Completed(Task completedTask)
- {
- if(completedTask.IsCanceled)
- Console.WriteLine("Cancelled");
- else
- Console.WriteLine("Completed");
- }
- }
- public class Worker
- {
- string context;
- ConcurrentQueue<Work> workQueue;
- CancellationToken cancelToken;
- public Worker(string context, ConcurrentQueue<Work> workQueue, CancellationToken cancelToken)
- {
- this.context = context;
- this.workQueue = workQueue;
- this.cancelToken = cancelToken;
- }
- public Task Start()
- {
- Task workerTask = new Task(Work);
- workerTask.Start();
- return workerTask;
- }
- private void Work()
- {
- while (workQueue.Any() && !cancelToken.IsCancellationRequested)
- {
- if (workQueue.TryDequeue(out Work work))
- {
- TimeSpan timeLeft = work.ExecuteAt - DateTime.Now;
- // basic load throttling, should be fixed to execution time rather than real time.
- if (timeLeft > TimeSpan.Zero)
- Task.Delay(timeLeft, cancelToken).ContinueWith(t => { }).Wait(); // this is strange :/
- if (!cancelToken.IsCancellationRequested)
- work.Execute(context);
- }
- }
- }
- }
- public abstract class Work
- {
- // when to be executed
- public DateTime ExecuteAt { get; set; }
- // what to be executed
- public abstract void Execute(string context);
- }
- public class Work1 : Work
- {
- public override void Execute(string context)
- {
- Console.WriteLine($"{context}1, delay: {Math.Round((ExecuteAt - DateTime.Now).TotalMilliseconds)} ms");
- var end = DateTime.Now + TimeSpan.FromSeconds(1);
- while (DateTime.Now < end)
- ;
- }
- }
- public class Work2 : Work
- {
- public override void Execute(string context)
- {
- Console.WriteLine($"{context}2, delay: {Math.Round((ExecuteAt - DateTime.Now).TotalMilliseconds)} ms");
- var end = DateTime.Now + TimeSpan.FromSeconds(2);
- while (DateTime.Now < end)
- ;
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement