I want to implement an Agent-like object in C#. An Agent wraps some memory location (ideally storing an immutable object) and receives updates to that location. All these updates are performed asynchronously, but sequentially. In other wordsAt any point in time, at most one [update submitted to an] Agent is  being executed.My current implementation uses the TPL. The Agent keeps a reference to the last update that has been or must be performed, wrapped in a Task. When submitted a new update, you wrap the update in a Task, get a reference to the last Task and replace it, atomically, then invoke ContinueWith on that last Task with this new update Task (everything submitted through a TaskScheduler).public class Agent<T> where T : class{    private T wrappedValue;    private readonly TaskScheduler scheduler;    private Task lastTask;    public Agent (T value, TaskScheduler scheduler)    {        this.wrappedValue = value;        this.scheduler = scheduler;    }    public void Send (Action<T> operation)    {        Task task = new Task ((action) => ((Action<T>)action) (wrappedValue), operation);        Task localCurrent;        do {            // always append to the end            localCurrent = lastTask;        } while(Interlocked.CompareExchange (ref lastTask, task, localCurrent) != localCurrent);        if (localCurrent == null) {            task.Start (scheduler);        } else {            localCurrent.ContinueWith ((currentTask, scheduler) => {                task.Start ((TaskScheduler)scheduler);            }, scheduler, scheduler);        }    }    [...]}The first thread to send an action will see null in the field and so needs to Start() the Task directly.This (seems to) work. Only one submitted action is ever running at a given moment. Additionally, tasks are potentially run on different threads. I don't want a dedicated thread for updates (and I don't want to lock up a TaskScheduler thread). However, I'm worried about a few things that I think could be improved:I'd like to be able to ContinueWith the Task task directly, instead of having to start it within a different submitted Action. I feel like I need to create the new Task so that I can atomically exchange the lastTask field's value.Lambda capturing of local variables, partly alleviated with state objects where possible.How can I keep a reference to the currently executing Task, so I can short-circuit execution? Or should I use a poison pill to signal termination and not chain any new tasks?Interlocked for atomicity. Should I use a ConcurrentQueue? How would I manage not having a dedicated thread and only running one Task at a time with a ConcurrentQueue?Is a Volatile.Read of lastTask necessary for localCurrent = lastTask;?Doing this nowprivate void InvokeAndComplete (Action<T> act, TaskCompletionSource<byte> promise){    try {        act (internalValue);    } finally {        // some value we will ignore        promise.SetResult (1);    }}public Task Alter (Action<T> alterAction){    TaskCompletionSource<byte> promise = new TaskCompletionSource<byte> ();    Task localLastTask;    do {        // Not sure if Volatile.Read is necessary        localLastTask = Volatile.Read (ref lastTask);    } while (Interlocked.CompareExchange (ref lastTask, promise.Task, localLastTask) != localLastTask);    // only this thread has a reference to the object referenced by localLastTask    return localLastTask.ContinueWith ((currentTask) => {        InvokeAndComplete (alterAction, promise);    }, taskScheduler);}
Chaining asynchronous tasks that must run sequentially
c#;multithreading;asynchronous