Run the most recently requested action after finishing current, skip middle tasks The goals for the code below are in the class summary below. Can anyone see that the code fails at any of those goals? I'm unsure how to thoroughly test it. Is there a way to keep the Queue method thread-safe and remove the lock? Is that lock even necessary?

/// &lt;summary&gt;
/// The goals: only run the most recently queued action. 
/// Do not run any actions simultaneously. 
/// Skip any tasks that were unstarted if we get a new one.
/// Cancel the currently running task (without aborting the thread).
/// (Rely upon the code in the action to bail early).
/// Support the "IsCanceled" flag on any task that was canceled or skipped.
/// &lt;/summary&gt;
public class SingleTaskQueue
{
    private Task _task = TaskUtilities.FromResult(false); // using Task.FromResult in .NET 4.5
    private CancellationTokenSource _cts = new CancellationTokenSource();
    private Action&lt;CancellationToken&gt; _action;
    public Task Queue(Action&lt;CancellationToken&gt; action) // this needs to be thread-safe
    {
        lock (_task) // yes, this changes with each call to Queue
        {
            _action = action;
            var newSource = new CancellationTokenSource();
            var tokenSource = Interlocked.Exchange(ref _cts, newSource);
            tokenSource.Cancel();
            var ret = _task.ContinueWith(justFinished =&gt; ProcessLastAction(newSource.Token), newSource.Token);
            _task = ret;
            return ret;
        }
    }

    private void ProcessLastAction(CancellationToken token)
    {
        if (!token.IsCancellationRequested)
        {
            Action&lt;CancellationToken&gt; last = Interlocked.Exchange(ref _action, null);
            if (last != null)
                last.Invoke(token);
        }
    }
}
Don't change the locks - You lock on _task, but inside the synchronized block - you change the reference to _task to a new object! This means that if threadA is in the block, threadB is waiting for the lock to release, and threadC calls the method exactly after threadA has run _task = ret; - threadC will be able to enter the block! This makes your lock mechanism fail.

If you want to lock a block - find a lock which defines the scope of your lock - and maintain it accordingly. In your example, the scope seems to be the instance of SingleTaskQueue. Since it is not advisable to do lock(this), create a private object _lock = new object(); and use it as your lock.

Mind your state - in ProcessLastAction you take your action from _action, to take only the last one, but you take the token as a parameter. This means that if two threads queue a new message before the last task finishes - the second _action may be invoked with the first token - which is already cancelled!

If the two objects are dependent of each other - maintain them together. Create a KeyValuePair&lt;CancellationToken, Action&gt; or a custom class to hold them both.

Is that lock necessary? I can't say if you really need the lock, as I don't know how would Task behave if ContinueWith is called twice on it: 


If the last call overrides the previous call (in a thread-safe manner) - you could do away with your whole solution - it could come down to a one-liner :)
If calls are aggregated in an internal queue, and your manual maintenance of the last action is needed, you would have to synchronize your work.


Also, if you have only a single producer thread (only one thread which calls Queue) - you don't need to synchronize.