# 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.

The class is NOT thread safe.

/// <summary>
/// THe class is NOT thread safe.
/// </summary>
{
private object m_pendingToken;

{
bool result = true;

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

// Make sure the current task completes.

// 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.
}

}

return result;
}

/// <summary>
/// Helper method. Will run the relevant task, maintaining class state.
/// </summary>
{
}
}

• Please do not just say: "Here's the code." and actually explain what your code does. – TheCoffeeCup Feb 5 '15 at 20:59
• More than willing to do that - but I added comments exactly for that - I will copy over the header comments which explain the matter. Thanks. – Shahar Prish Feb 6 '15 at 6:14
• Please describe the use cases for this class. I assume you have the Func<Task> parameter so that you call it only in case when the task should be executed, am I correct? – almaz Feb 6 '15 at 14:28
• Added a description. And yes - because I dont want the task to just start running, I need a Func to issue it. – Shahar Prish Feb 7 '15 at 6:01
• @ShaharPrish your code will always execute the task and will always return true because nobody else is changing m_pendingToken. – Bruno Costa Feb 7 '15 at 8:23

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

{
lock (m_pendingToken)
{
//No need in double-checked locking as the last wins
}

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

//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
return false;

lock (m_pendingToken)
{
return false;


• locking is done in order not to allow 2 different threads to modify m_nextTaskFunc at the same time. There is a lock-free solution as well, but it would require additional TaskCompletionSource and a loop to make sure this thread is the "winner", and to evaluate taskFunc only in case of winning the race. – almaz Feb 19 '15 at 6:54