Just create a class that keeps track of the current task in progress, the action that will be performed next, and the "next" action when the previous action ends. The key point here is that if the next action matters, when you go into the new queue, you can just replace it nextTaskinstead of adding another continuation.
public class TaskQueue
{
private Task currentlyExecuting = Task.FromResult(false);
public Task continuation = null;
private CancellationTokenSource cts = new CancellationTokenSource();
private Action nextTask = null;
private object key = new object();
public Task Queue(Action action)
{
lock (key)
{
if (nextTask == null)
{
nextTask = action;
ScheduleContinuation();
return continuation;
}
else
{
cts.Cancel();
nextTask = action;
ScheduleContinuation();
return continuation;
}
}
}
private void ScheduleContinuation()
{
cts = new CancellationTokenSource();
var token = cts.Token;
continuation = currentlyExecuting.ContinueWith(t =>
{
lock (key)
{
currentlyExecuting = Task.Run(nextTask);
token.ThrowIfCancellationRequested();
nextTask = null;
}
}, cts.Token);
}
}
, , , , .