A utility class for running up to two Tasks serially, where the last task to be queued "wins"
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;
    }
}