Skip to content

Instantly share code, notes, and snippets.

@ocoanet ocoanet/Sequencer V2

Last active Aug 29, 2015
Embed
What would you like to do?
Task based sequencer
using System;
using System.Threading;
using System.Threading.Tasks;
using log4net;
namespace Seq
{
// note: I do not usually comment my code that much :)
public class Sequencer
{
private readonly ILog _logger = LogManager.GetLogger(typeof(Sequencer));
private readonly object _lock = new object();
private readonly TaskScheduler _taskScheduler;
private Task _task = Task.FromResult(0);
private int _pendingTaskCount;
public Sequencer() : this(TaskScheduler.Current)
{
}
public Sequencer(TaskScheduler taskScheduler)
{
// we could need to specify a custom scheduler, in order to limit concurrency, or for testing purpose
_taskScheduler = taskScheduler;
}
// so the pending task count can be controlled or monitored from the outside
public int PendingTaskCount
{
get { return _pendingTaskCount; }
}
public void Dispatch(Action action)
{
// it might be a good idea ensure _pendingTaskCount is above a max value
// when it is beyond the max we could block, discard updates, throw or do anything that seems appropriate
var continuationAction = BuildContinuationAction(action);
lock (_lock)
{
_task = _task.ContinueWith(continuationAction, _taskScheduler);
}
}
private Action<Task> BuildContinuationAction(Action action)
{
Interlocked.Increment(ref _pendingTaskCount);
return previousTask =>
{
// tasks are not supposed to be disposed (http://blogs.msdn.com/b/pfxteam/archive/2012/03/25/10287435.aspx)
// but I feel more confortable doing it, because tasks are finalizable
previousTask.Dispose();
try
{
action();
}
catch (Exception ex)
{
_logger.ErrorFormat("Dispatch action failed: {0}", ex);
}
Interlocked.Decrement(ref _pendingTaskCount);
};
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.