Skip to content

Instantly share code, notes, and snippets.

@blitzxion
Created March 9, 2015 19:29
Show Gist options
  • Select an option

  • Save blitzxion/64e4f60d56fbd9633364 to your computer and use it in GitHub Desktop.

Select an option

Save blitzxion/64e4f60d56fbd9633364 to your computer and use it in GitHub Desktop.
// Written for LinqPad, sorry guys
async void Main()
{
var pm = new PollerManager();
// var task1 = pm.Create(() => { @"LOOP 1".Dump(); }, () => { @"DONE 1".Dump(); }, TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(5));
// var task2 = pm.Create(() => { @"LOOP 2".Dump(); }, () => { @"DONE 2".Dump(); }, TimeSpan.FromSeconds(2), TimeSpan.FromSeconds(10));
for (int i = 0; i < 10; i++) {
pm.Create(
string.Format(@"TASK_{0}", i),
(x) => { string.Format(@"[{0}] LOOPED {1} TIMES", x.Name, x.NumTimesLooped).Dump(); },
(x) => { string.Format(@"[{0}] COMPLETED AFTER {1} LOOPS", x.Name, x.NumTimesLooped).Dump(); },
TimeSpan.FromSeconds(i + 1),
TimeSpan.FromSeconds(i + 10)
);
}
// Run my tasks
Task.Run(async() => {
await pm.RunAll();
});
await Task.Delay(TimeSpan.FromSeconds(15));
// Cancel all my tasks
pm.StopAll();
@"COMPLETE".Dump();
}
// Define other methods and classes here
public class PollerManager
{
readonly List<PollerTaskContainer> TaskList;
public PollerManager() {
TaskList = new List<PollerTaskContainer>(10);
}
public PollerTaskContainer Create (string name, Action<PollerTaskContainer> onPoll, Action<PollerTaskContainer> onEnd, TimeSpan interval, TimeSpan timeout) {
var newTask = new PollerTaskContainer(name, onPoll, onEnd, interval, timeout);
TaskList.Add(newTask);
return newTask;
}
public PollerTaskContainer Create (PollerTaskContainer newTask) {
TaskList.Add(newTask);
return newTask;
}
public async Task RunAll() {
if(TaskList != null) {
var availableTasks = TaskList.Where (x => !x.IsRunning);
string.Format(@"STARTING {0} TASK(S)", availableTasks.Count()).Dump();
await Task.WhenAll(availableTasks.Select (x => { return x.Run(); }));
}
}
public void StopAll() {
if(TaskList != null) {
@"STOPPING ALL TASKS".Dump();
TaskList.ForEach(x => x.Stop()); // Stop them all...
TaskList.Clear(); // Remove all tasks
}
}
}
public class PollerTaskContainer
{
public string Name { get; private set; }
public int NumTimesLooped { get; private set; }
CancellationTokenSource CTS { get; set; }
TimeSpan PollInterval { get; set; }
TimeSpan PollTimeout { get; set; }
Action<PollerTaskContainer> OnEndAction { get; set; }
Action<PollerTaskContainer> OnPollAction { get; set; }
public bool IsRunning { get { return (CTS!=null) ? !CTS.IsCancellationRequested : false; } }
/// Create a Task that acts on poll, with an action when it ends, on an interval, with a timeout
public PollerTaskContainer(string name, Action<PollerTaskContainer> onPoll, Action<PollerTaskContainer> onEnd, TimeSpan interval, TimeSpan timeout) {
Name = name;
OnPollAction = onPoll;
OnEndAction = onEnd;
PollInterval = interval;
PollTimeout = timeout;
}
public async Task Run() {
if(CTS != null && !CTS.IsCancellationRequested) {
CTS.Token.Register(()=>{ }); // Remove the onEndAction
CTS.Cancel();
}
NumTimesLooped = 0;
CTS = new CancellationTokenSource();
CTS.Token.Register(() => { if(OnEndAction != null) OnEndAction(this); });
CTS.CancelAfter(PollTimeout);
await PeriodicTask.Run(() => { NumTimesLooped++; if(OnPollAction != null) OnPollAction(this); }, PollInterval, CTS.Token);
}
public void Stop() {
if(CTS != null && !CTS.IsCancellationRequested) {
CTS.Cancel();
}
}
}
public static class PeriodicTask {
public static async Task Run(Action action, TimeSpan period, CancellationToken cancellationToken) {
while(!cancellationToken.IsCancellationRequested) {
try {
await Task.Delay (period, cancellationToken);
action ();
} catch (TaskCanceledException) {
// DO NOTHING. IT WAS CANCELLED... GEEZ MICROSOFT
}
}
}
public static Task Run(Action action, TimeSpan period) {
return Run(action, period, CancellationToken.None);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment