Run only the current task and the most recent task in the queue

I have several methods. We will call them TurnOn and TurnOff. Each returns a non-running task (as in System.Threading.Tasks.Task). After starting, the task takes about a second. I have some code to queue them using the Task.ContinueWith method (shown here ). The problem is that I really want only the current task (if any) and the last task requested to be executed. Currently, if my user switches the on / off switch ten times per second, it takes my code twenty seconds to catch up. This is just the last request that worries me. How can I achieve this? I see no way inside the ContinueWith method to find out if there is another ContinueWith method after it.I looked at an examplehere , but don't quite understand how to apply it.

Update: it is now available in the library here: https://github.com/BrannonKing/Kts.ActorsLite . It is called "MostRecent ..."

+4
source share
1 answer

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);
    }
}

, , , , .

+3

All Articles