Last active
August 29, 2015 14:01
-
-
Save ocoanet/e20aadf323663f56229f to your computer and use it in GitHub Desktop.
Task based sequencer
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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