A utility class for running up to two Tasks serially, where the last task to be queued "wins" Edit: Use cases for this class - I needed this class in the case where I had processes I needed to execute (in the form of tasks - they were all asynchronous) that I needed to issue to a UI control when certain events occurred. However, these events are something I dont control and can sometimes occur in close succession. This class is used to make sure only the last event to have issued the task will "win" and run the task only once.

This class lets you run multiple tasks serially. If a task is already running (Task1), the next task (Task2) is "queued". However, if, before Task1 completes, Task3 is executed, it will replace Task2 and will be executed next.

The class is NOT thread safe.

/// &lt;summary&gt;
/// Lets you run multiple tasks serially. If a task is already running (Task1), the next task (Task2) is "queued". However, if,
/// before Task1 completes, Task3 is executed, it will replace Task2 and will be executed next.
/// THe class is NOT thread safe.
/// &lt;/summary&gt;
public class LastTaskWins
{
    private object m_pendingToken;
    private Task m_currentTask;


    public async Task&lt;bool&gt; TryRunAsync(Func&lt;Task&gt; taskFunc)
    {
        bool result = true;

        // If there is no task running, just run the one queued.
        if (m_currentTask == null)
        {
            await ExecuteTaskNowAsync(taskFunc);
        }
        else
        {
            // Save a token so we know if we can run.
            object token = m_pendingToken = new object();

            // Make sure the current task completes.
            await m_currentTask;

            // Check to see if a new task has been "queued".
            result = token == m_pendingToken;
            if (result)
            {
                // If we can run (we own the last-queued task token), run the new task.
                await ExecuteTaskNowAsync(taskFunc);
            }

        }

        return result;
    }

    /// &lt;summary&gt;
    /// Helper method. Will run the relevant task, maintaining class state.
    /// &lt;/summary&gt;
    private async Task ExecuteTaskNowAsync(Func&lt;Task&gt; taskFunc)
    {
        m_currentTask = taskFunc();
        await m_currentTask;
        m_currentTask = null;
    }
}
I suggest to make m_currentTask non-nullable by replacing usages of null with a completed task. It will simplify the code as you can always await on this field, and assume it is the "current" task running.

You would need to introduce locking in order to synchronize access to the continuation task, and ensure that the taskFunc is only called when it was a winning bid. Also, you would need a double-checked locking to ensure that your task is the winner:

public class LastTaskWins
{
    private readonly object m_pendingToken = new object();
    private Task m_currentTask = Task.FromResult(true); //It will always have a non-null value that you can await on
    private Func&lt;Task&gt; m_nextTaskFunc;


    public async Task&lt;bool&gt; TryRunAsync(Func&lt;Task&gt; taskFunc)
    {
        lock (m_pendingToken)
        {
            //No need in double-checked locking as the last wins
            m_nextTaskFunc = taskFunc;
        }

        // Current task is always present, and may already be completed (in which case await would run synchronously).
        await m_currentTask;

        Task currentTask;

        //Using double-checked locking to make sure we don't have concurrency issues around continuation task, and we only call taskFunc when going to await on it
        if (m_nextTaskFunc != taskFunc)
            return false;

        lock (m_pendingToken)
        {
            if (m_nextTaskFunc != taskFunc)
                return false;

            currentTask = m_currentTask = taskFunc();
            m_nextTaskFunc = null; //just to clean up the reference, as may represent a memory leak otherwise
        }

        await currentTask;
        return true;
    }
}