diff --git a/src/NewRemoting/Toolkit/ITaskQueue.cs b/src/NewRemoting/Toolkit/ITaskQueue.cs index b4539d5..e9078ea 100644 --- a/src/NewRemoting/Toolkit/ITaskQueue.cs +++ b/src/NewRemoting/Toolkit/ITaskQueue.cs @@ -1,9 +1,10 @@ using System; +using System.Collections.Generic; using System.Threading.Tasks; namespace NewRemoting.Toolkit { - public interface ITaskQueue + public interface ITaskQueue : IEnumerable { /// /// Returns the number of tasks in the queue @@ -20,17 +21,17 @@ int Count bool TryAdd(Action action); /// - /// Adds a delegate with parameters for sequential execution to the task queue. - /// Attention: Less performant than using an action. - /// Returns false if queue is disabled. + /// Tries to add an action for sequential execution to the task queue. + /// Throws if queue is disabled. The provided tag argument is readable + /// from outside and provided as argument to the action once it is started. /// - bool TryAdd(Delegate del, object[] para); + void Add(Action action, T tag); /// - /// Adds a task for sequential execution to the task queue. + /// Tries to add an action for sequential execution to the task queue. /// Returns false if queue is disabled. /// - bool TryAdd(Task task); + bool TryAdd(Action action, T tag); /// /// Tries to add an action for sequential execution to the task queue. @@ -38,19 +39,6 @@ int Count /// void Add(Action action); - /// - /// Adds a delegate with parameters for sequential execution to the task queue. - /// Attention: Less performant than using an action. - /// Throws if queue is disabled. - /// - void Add(Delegate del, object[] para); - - /// - /// Adds a task for sequential execution to the task queue. - /// Throws if queue is disabled. - /// - void Add(Task task); - /// /// Waits until the tasks queue becomes empty /// and all remaining tasks have finished diff --git a/src/NewRemoting/Toolkit/TaskQueue.cs b/src/NewRemoting/Toolkit/TaskQueue.cs index b2ba474..f2ee4aa 100644 --- a/src/NewRemoting/Toolkit/TaskQueue.cs +++ b/src/NewRemoting/Toolkit/TaskQueue.cs @@ -1,19 +1,23 @@ using System; +using System.Collections; using System.Collections.Generic; using System.Diagnostics; +using System.Linq; using System.Threading; using System.Threading.Tasks; namespace NewRemoting.Toolkit { /// - /// This class ensures, that all tasks passed to the queue are executed in sequential order + /// This class ensures, that all tasks passed to the queue are executed in sequential order. + /// Every task can have an object assigned to it that can also be queried from outside (e.g. to identify + /// what kind of tasks is in the queue) /// - public sealed class TaskQueue : ITaskQueue + public class TaskQueue : ITaskQueue { private readonly Action _exceptionHandler; private readonly object _queueLock = new object(); - private Queue _taskQueue; + private Queue<(Task Task, T Tag)> _taskQueue; private Task _currentTask; /// @@ -21,7 +25,7 @@ public sealed class TaskQueue : ITaskQueue /// public TaskQueue() { - _taskQueue = new Queue(); + _taskQueue = new Queue<(Task, T)>(); _currentTask = null; } @@ -57,19 +61,22 @@ public int Count } } - public void Add(Action action) + public IEnumerator GetEnumerator() { - AddInternal(action, true); + lock (_queueLock) + { + return _taskQueue.Select(x => x.Tag).GetEnumerator(); + } } - public void Add(Delegate del, object[] para) + IEnumerator IEnumerable.GetEnumerator() { - AddInternal(del, para, true); + return GetEnumerator(); } - public void Add(Task task) + public void Add(Action action) { - AddInternal(task, true); + AddInternal(action, true); } public bool TryAdd(Action action) @@ -77,40 +84,26 @@ public bool TryAdd(Action action) return AddInternal(action, false); } - /// - /// Attention: is very slow consider wrapping time critical stuff into an action . - /// - /// Add(new Action(() => Call(p1, p2, p3, ...)); - /// - /// - public bool TryAdd(Delegate del, object[] para) + public void Add(Action action, T tag) { - return AddInternal(del, para, false); + AddInternal(action, tag, true); } - public bool TryAdd(Task task) + public bool TryAdd(Action action, T tag) { - return AddInternal(task, false); + return AddInternal(action, tag, false); } private bool AddInternal(Action action, bool throwOnDisabled) { - return AddInternal(new Task(action), throwOnDisabled); - } - - /// - /// is very slow - /// - private bool AddInternal(Delegate del, object[] para, bool throwOnDisabled) - { - return AddInternal(new Task(() => del.DynamicInvoke(para)), throwOnDisabled); + return AddInternal(x => action(), default, throwOnDisabled); } /// /// Adds a Tasks to the task Queue /// /// Adding tasks to disabled queue is not allowed - private bool AddInternal(Task task, bool throwOnDisabled) + private bool AddInternal(Action action, T tag, bool throwOnDisabled) { var added = false; lock (_queueLock) @@ -122,7 +115,7 @@ private bool AddInternal(Task task, bool throwOnDisabled) if (_taskQueue != null) { - _taskQueue.Enqueue(task); + _taskQueue.Enqueue((new Task(() => action(tag)), tag)); added = true; } @@ -179,7 +172,7 @@ private void RunTask() if (_currentTask == null && _taskQueue != null && _taskQueue.Count > 0) { // Leave currently executing task in queue until fully executed, this makes waiting for all tasks executed much easier than when removing here and handling the currently executing task separately - _currentTask = _taskQueue.Peek(); + (_currentTask, _) = _taskQueue.Peek(); var whereToContinueTask = _currentTask; if (_exceptionHandler != null) { @@ -207,4 +200,16 @@ private void OnTaskFinished(Task finishedTask) } } } + + public class TaskQueue : TaskQueue + { + public TaskQueue() + { + } + + public TaskQueue(Action exceptionHandler) + : base(exceptionHandler) + { + } + } }