/// <summary> /// , /// . /// </summary> /// <remarks> /// . /// </remarks> public sealed class FixedThreadPool { #region Constructors /// <summary> /// /// . /// </summary> /// <param name="aConcurrentTaskNumber"> /// . /// </param> /// <param name="aLog"> /// . /// </param> /// <param name="aPriorityLog"> /// . /// </param> /// <exception cref="ArgumentOutOfRangeException"> /// . /// </exception> public FixedThreadPool (int aConcurrentTaskNumber, ILog aLog = null, ILog aPriorityLog = null) { if (aConcurrentTaskNumber <= 1) { throw new ArgumentOutOfRangeException( "aConcurrentTaskNumber", " ."); } Log = aLog; PriorityLog = aPriorityLog; mConcurrentTaskNumber = aConcurrentTaskNumber; LogMessage(" ."); Thread lTaskSchedulerThread = new Thread(TaskSchedulerLogic) {Name = " ."}; lTaskSchedulerThread.Start(); LogMessage(" ."); } #endregion #region Public methods /// <summary> /// <paramref name="aTask"/> /// <paramref name="aTaskPriority"/>. /// </summary> /// <param name="aTask"> /// .. /// </param> /// <param name="aTaskPriority"> /// . /// </param> /// <returns> /// <see langword="true"/> - . /// <see langword="false"/> - , /// . /// </returns> /// <exception cref="ArgumentNullException"> /// . /// </exception> public bool Execute(Task aTask, TaskPriority aTaskPriority) { if (aTask == null) { throw new ArgumentNullException( "aTask", " ."); } LogMessage(" ."); lock (mIsStoppedLock) { if (IsStopped) { // . LogPriority(aTaskPriority, ConsoleColor.DarkGray); // . return false; } } // . EnqueueTask(aTask, aTaskPriority); LogMessage(" .", ConsoleColor.DarkYellow); return true; } /// <summary> /// , . /// . /// </summary> /// <remarks> /// /// <see cref="Execute"/> <see langword="false"/>. /// , , . /// </remarks> public void Stop() { // . lock (mIsStoppedLock) { IsStopped = true; LogMessage(" ."); } // , . LogMessage( " .", ConsoleColor.DarkRed); lock (mTaskSchedulerLock) { // mTaskSchedulerLock. Monitor.Pulse(mTaskSchedulerLock); } mPoolStoppedGate.WaitOne(); LogMessage(" .", ConsoleColor.DarkRed); } #endregion #region Private properties /// <summary> /// / , . /// </summary> /// <value> /// <see langword="true"/> - , /// . <see langword="false"/> - . /// </value> /// <remarks> /// <see cref="mIsStoppedLock"/>. /// </remarks> private bool IsStopped { get; set; } /// <summary> /// / . /// </summary> private ILog PriorityLog { get; set; } /// <summary> /// / . /// </summary> private ILog Log { get; set; } #endregion #region Private methods /// <summary> /// . . /// </summary> private void TaskSchedulerLogic() { lock (mTaskSchedulerLock) { while (true) { // , mTaskSchedulerLock. Monitor.Wait(mTaskSchedulerLock); lock (mQueuedTasksLock) { lock (mIsStoppedLock) { lock (mRunningTasksLock) { if (IsStopped && !mRunningTasks.Any() && !mQueuedTasks.Any()) { LogMessage( " ."); LogMessage(" - ."); // . mPoolStoppedGate.Set(); return; } } } } lock (mQueuedTasksLock) { if (!mQueuedTasks.Any()) { // . // . continue; } } lock (mRunningTasksLock) { if (mRunningTasks.Count >= mConcurrentTaskNumber) { // . // . continue; } } LogMessage( " .", ConsoleColor.DarkRed); // . TaskListEntry lTask = DequeueTask(); LogMessage(" - ."); // . lTask.Task.Finished += OnTaskFinished; // . lock (mRunningTasksLock) { mRunningTasks.Add(lTask); } if (lTask.TaskPriority == TaskPriority.High) { // . // . Interlocked.Increment(ref mQueuedHighPriorityTaskCounter); } else if (lTask.TaskPriority == TaskPriority.Normal) { // . // HighPriorityTaskFactor. Interlocked.Add( ref mQueuedHighPriorityTaskCounter, -HighPriorityTaskFactor); } // . lTask.Task.Execute(); LogMessage( string.Format( " - {0}.", lTask.TaskPriority), ConsoleColor.DarkYellow); lock (mRunningTasksLock) { LogMessage( string.Format( " {0} .", mRunningTasks.Count)); } } } } /// <summary> /// . /// </summary> /// <param name="aSender"> /// - . /// </param> /// <param name="aEventArgs"> /// . /// </param> private void OnTaskFinished(object aSender, EventArgs aEventArgs) { Task lSender = aSender as Task; Debug.Assert( lSender != null, " aSender ."); // , . lSender.Finished -= OnTaskFinished; // . lock (mRunningTasksLock) { // . TaskListEntry lEntry = mRunningTasks.First(aEntry => aEntry.Task == lSender); mRunningTasks.Remove(lEntry); LogMessage( string.Format(" {0} .", lEntry.TaskPriority), ConsoleColor.Red); } lock (mTaskSchedulerLock) { // mTaskSchedulerLock. Monitor.Pulse(mTaskSchedulerLock); } } /// <summary> /// <paramref name="aTask"/> . /// </summary> /// <param name="aTask"> /// , . /// </param> /// <param name="aTaskPriority"> /// . /// </param> private void EnqueueTask(Task aTask, TaskPriority aTaskPriority) { TaskListEntry lEntry = new TaskListEntry(aTask, aTaskPriority); LogPriority(aTaskPriority, ConsoleColor.Green); lock (mQueuedTasksLock) { // . mQueuedTasks.Add(lEntry); LogMessage( string.Format( " {0}", lEntry.TaskPriority), ConsoleColor.Green); // . LogMessage(" .", ConsoleColor.DarkRed); } lock (mTaskSchedulerLock) { // mTaskSchedulerLock. Monitor.Pulse(mTaskSchedulerLock); } } /// <summary> /// . /// , . /// </summary> /// <returns> /// , . /// </returns> private TaskListEntry DequeueTask() { TaskListEntry lNextTask; lock (mQueuedTasksLock) { lNextTask = FindNextTaskUsingPriorityRules(); LogPriority(lNextTask.TaskPriority, ConsoleColor.Red); LogMessage( string.Format( " {0}.", lNextTask.TaskPriority), ConsoleColor.DarkRed); mQueuedTasks.Remove(lNextTask); } lock (mTaskSchedulerLock) { // mTaskSchedulerLock. Monitor.Pulse(mTaskSchedulerLock); } return lNextTask; } /// <summary> /// . /// </summary> /// <returns> /// . /// </returns> /// <remarks> /// : /// . , , /// . , /// , , . /// , , -, /// - . /// </remarks> private TaskListEntry FindNextTaskUsingPriorityRules() { TaskListEntry lNextTask; lock (mQueuedTasksLock) { Debug.Assert( mQueuedTasks.Count > 0, " FindNextTaskUsingPriorityRules , ."); // . TaskPriority lNextTaskPriority = TaskPriority.High; // . if (mQueuedTasks.All(aEntry => aEntry.TaskPriority == TaskPriority.Low)) { // . // . lNextTaskPriority = TaskPriority.Low; } else { // . if (mQueuedTasks.Any( aEntry => aEntry.TaskPriority == TaskPriority.Normal) && (mQueuedTasks.All( aEntry => aEntry.TaskPriority != TaskPriority.High) || Interlocked.CompareExchange(ref mQueuedHighPriorityTaskCounter, 0, 0) >= HighPriorityTaskFactor)) { // // // . // . lNextTaskPriority = TaskPriority.Normal; } } lNextTask = mQueuedTasks.First( aEntry => aEntry.TaskPriority == lNextTaskPriority); } return lNextTask; } /// <summary> /// . /// </summary> /// <param name="aMessage"> /// . /// </param> /// <param name="aColor"> /// . /// </param> private void LogMessage(string aMessage, ConsoleColor aColor = ConsoleColor.Yellow) { if (Log == null) { return; } Log.WriteMessage(aMessage, aColor); } /// <summary> /// . /// </summary> /// <param name="aTaskPriority"> /// . /// </param> /// <param name="aColor"> /// . /// </param> private void LogPriority(TaskPriority aTaskPriority, ConsoleColor aColor) { if (PriorityLog == null) { return; } string lPriority = aTaskPriority == TaskPriority.High ? "H" : aTaskPriority == TaskPriority.Normal ? "N" : "L"; PriorityLog.WriteMessage(lPriority, aColor); } #endregion #region Private data /// <summary> /// , /// , , /// . /// </summary> private const int HighPriorityTaskFactor = 3; /// <summary> /// . /// . /// </summary> private readonly int mConcurrentTaskNumber; /// <summary> /// <see cref="IsStopped"/>. /// </summary> private readonly object mIsStoppedLock = new object(); /// <summary> /// . , /// . /// </summary> private readonly ManualResetEvent mPoolStoppedGate = new ManualResetEvent(false); /// <summary> /// , . /// </summary> /// <remarks> /// <see cref="mQueuedTasksLock"/>. /// </remarks> private readonly IList<TaskListEntry> mQueuedTasks = new List<TaskListEntry>(); /// <summary> /// <see cref="mQueuedTasks"/>. /// </summary> private readonly object mQueuedTasksLock = new object(); /// <summary> /// . /// </summary> /// <remarks> /// <see cref="mRunningTasksLock"/>. /// </remarks> private readonly IList<TaskListEntry> mRunningTasks = new List<TaskListEntry>(); /// <summary> /// <see cref="mRunningTasks"/>. /// </summary> private readonly object mRunningTasksLock = new object(); /// <summary> /// , / . /// </summary> private readonly object mTaskSchedulerLock = new object(); /// <summary> /// , . /// , /// <see cref="HighPriorityTaskFactor"/>. /// </summary> /// <remarks> /// /// <see cref="Interlocked"/>. /// </remarks> private int mQueuedHighPriorityTaskCounter; #endregion #region Nested type: TaskListEntry /// <summary> /// . /// </summary> /// <remarks> /// . /// </remarks> private struct TaskListEntry { #region Constructors /// <summary> /// . /// </summary> /// <param name="aTask"> /// . /// </param> /// <param name="aTaskPriority"> /// . /// </param> public TaskListEntry(Task aTask, TaskPriority aTaskPriority) { mTask = aTask; mTaskPriority = aTaskPriority; } #endregion #region Public properties /// <summary> /// . /// </summary> public Task Task { get { return mTask; } } /// <summary> /// . /// </summary> public TaskPriority TaskPriority { get { return mTaskPriority; } } #endregion #region Private data private readonly Task mTask; private readonly TaskPriority mTaskPriority; #endregion } #endregion }
/// <summary> /// <see cref="FixedThreadPool1"/>. /// </summary> public class Task { #region Constructors /// <summary> /// <see cref="FixedThreadPool1"/> /// . /// </summary> /// <param name="aTaskBody"> /// . /// </param> /// <exception cref="ArgumentNullException"> /// . /// </exception> public Task(Action aTaskBody) { if (aTaskBody == null) { throw new ArgumentNullException("aTaskBody", " ."); } TaskBody = aTaskBody; } #endregion #region Public properties /// <summary> /// / . /// </summary> public Action TaskBody { get; private set; } #endregion #region Events /// <summary> /// , . /// </summary> public event EventHandler Finished; #endregion #region Public methods /// <summary> /// . /// </summary> public void Execute() { Thread lTaskThread = new Thread( () => { // . TaskBody(); // . EventHandler lFinished = Finished; if (lFinished != null) { lFinished(this, EventArgs.Empty); } }) {Name = "Task thread."}; lTaskThread.Start(); } #endregion }
/// <summary> /// . /// </summary> public enum TaskPriority { /// <summary> /// . /// </summary> High = 0, /// <summary> /// . /// </summary> Normal, /// <summary> /// . /// </summary> Low }
// : Eshva.Threading // : FixedThreadPool.cs // GUID : 7F1EECB7-F28A-4A20-9536-26D174BCD437 // : Mike Eshva (mike@eshva.ru) // : 04.06.2012 using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Threading; namespace Eshva.Threading.Framework { /// <summary> /// , /// . /// </summary> /// <remarks> /// . /// </remarks> public sealed class FixedThreadPool { #region Constructors /// <summary> /// /// . /// </summary> /// <param name="aConcurrentTaskNumber"> /// . /// </param> /// <param name="aLog"> /// . /// </param> /// <param name="aPriorityLog"> /// . /// </param> /// <exception cref="ArgumentOutOfRangeException"> /// . /// </exception> public FixedThreadPool (int aConcurrentTaskNumber, ILog aLog = null, ILog aPriorityLog = null) { if (aConcurrentTaskNumber <= 1) { throw new ArgumentOutOfRangeException( "aConcurrentTaskNumber", " ."); } Log = aLog; PriorityLog = aPriorityLog; for (int lThreadIndex = 0; lThreadIndex < aConcurrentTaskNumber; lThreadIndex++) { string lThreadName = string.Format("Task thread #{0}", lThreadIndex); Thread lTaskThread = new Thread(TaskThreadLogic) {Name = lThreadName}; lTaskThread.Start(); } } #endregion #region Public methods /// <summary> /// <paramref name="aTask"/> /// <paramref name="aTaskPriority"/>. /// </summary> /// <param name="aTask"> /// .. /// </param> /// <param name="aTaskPriority"> /// . /// </param> /// <returns> /// <see langword="true"/> - . /// <see langword="false"/> - , /// . /// </returns> /// <exception cref="ArgumentNullException"> /// . /// </exception> public bool Execute(Task aTask, TaskPriority aTaskPriority) { if (aTask == null) { throw new ArgumentNullException( "aTask", " ."); } LogMessage(" ."); lock (mIsStoppedLock) { if (IsStopped) { // . LogPriority(aTaskPriority, ConsoleColor.DarkGray); // . return false; } } // . EnqueueTask(aTask, aTaskPriority); LogMessage(" .", ConsoleColor.DarkYellow); return true; } /// <summary> /// , . /// . /// </summary> /// <remarks> /// /// <see cref="Execute"/> <see langword="false"/>. /// , , . /// </remarks> public void Stop() { // . lock (mIsStoppedLock) { IsStopped = true; LogMessage(" ."); } // , . LogMessage( " .", ConsoleColor.DarkRed); lock (mTaskSchedulerLock) { // mTaskSchedulerLock. Monitor.PulseAll(mTaskSchedulerLock); } mPoolStoppedGate.WaitOne(); LogMessage(" .", ConsoleColor.DarkRed); } #endregion #region Private properties /// <summary> /// / , . /// </summary> /// <value> /// <see langword="true"/> - , /// . <see langword="false"/> - . /// </value> /// <remarks> /// <see cref="mIsStoppedLock"/>. /// </remarks> private bool IsStopped { get; set; } /// <summary> /// / . /// </summary> private ILog PriorityLog { get; set; } /// <summary> /// / . /// </summary> private ILog Log { get; set; } #endregion #region Private methods private void TaskThreadLogic() { lock (mTaskSchedulerLock) { while (true) { // , mTaskSchedulerLock. Monitor.Wait(mTaskSchedulerLock); lock (mQueuedTasksLock) { if (!mQueuedTasks.Any()) { lock (mIsStoppedLock) { if (IsStopped) { LogMessage( " ."); LogMessage(" - ."); // . mPoolStoppedGate.Set(); return; } } // , . // . continue; } } LogMessage( " .", ConsoleColor.DarkRed); // . TaskListEntry lTask = DequeueTask(); LogMessage(" - ."); switch (lTask.TaskPriority) { case TaskPriority.High: Interlocked.Increment(ref mQueuedHighPriorityTaskCounter); break; case TaskPriority.Normal: Interlocked.Add( ref mQueuedHighPriorityTaskCounter, -HighPriorityTaskFactor); break; } // . lTask.Task.Execute(); LogMessage( string.Format( " - {0}.", lTask.TaskPriority), ConsoleColor.DarkYellow); lock (mQueuedTasksLock) { lock (mIsStoppedLock) { if (IsStopped && !mQueuedTasks.Any()) { LogMessage( " ."); LogMessage(" - ."); // . mPoolStoppedGate.Set(); return; } } } } } } /// <summary> /// <paramref name="aTask"/> . /// </summary> /// <param name="aTask"> /// , . /// </param> /// <param name="aTaskPriority"> /// . /// </param> private void EnqueueTask(Task aTask, TaskPriority aTaskPriority) { TaskListEntry lEntry = new TaskListEntry(aTask, aTaskPriority); LogPriority(aTaskPriority, ConsoleColor.Green); lock (mQueuedTasksLock) { // . mQueuedTasks.Add(lEntry); LogMessage( string.Format( " {0}", lEntry.TaskPriority), ConsoleColor.Green); // . LogMessage(" .", ConsoleColor.DarkRed); } lock (mTaskSchedulerLock) { // mTaskSchedulerLock. Monitor.Pulse(mTaskSchedulerLock); } } /// <summary> /// . /// , . /// </summary> /// <returns> /// , . /// </returns> private TaskListEntry DequeueTask() { TaskListEntry lNextTask; lock (mQueuedTasksLock) { lNextTask = FindNextTaskUsingPriorityRules(); LogPriority(lNextTask.TaskPriority, ConsoleColor.Red); LogMessage( string.Format( " {0}.", lNextTask.TaskPriority), ConsoleColor.DarkRed); mQueuedTasks.Remove(lNextTask); } lock (mTaskSchedulerLock) { // mTaskSchedulerLock. Monitor.Pulse(mTaskSchedulerLock); } return lNextTask; } /// <summary> /// . /// </summary> /// <returns> /// . /// </returns> /// <remarks> /// : /// . , , /// . , /// , , . /// , , -, /// - . /// </remarks> private TaskListEntry FindNextTaskUsingPriorityRules() { TaskListEntry lNextTask; lock (mQueuedTasksLock) { Debug.Assert( mQueuedTasks.Count > 0, " FindNextTaskUsingPriorityRules , ."); // . TaskPriority lNextTaskPriority = TaskPriority.High; // . if (mQueuedTasks.All(aEntry => aEntry.TaskPriority == TaskPriority.Low)) { // . // . lNextTaskPriority = TaskPriority.Low; } else { // . if (mQueuedTasks.Any( aEntry => aEntry.TaskPriority == TaskPriority.Normal) && (mQueuedTasks.All( aEntry => aEntry.TaskPriority != TaskPriority.High) || Interlocked.CompareExchange(ref mQueuedHighPriorityTaskCounter, 0, 0) >= HighPriorityTaskFactor)) { // // // . // . lNextTaskPriority = TaskPriority.Normal; } } lNextTask = mQueuedTasks.First( aEntry => aEntry.TaskPriority == lNextTaskPriority); } return lNextTask; } /// <summary> /// . /// </summary> /// <param name="aMessage"> /// . /// </param> /// <param name="aColor"> /// . /// </param> private void LogMessage(string aMessage, ConsoleColor aColor = ConsoleColor.Yellow) { if (Log == null) { return; } Log.WriteMessage(aMessage, aColor); } /// <summary> /// . /// </summary> /// <param name="aTaskPriority"> /// . /// </param> /// <param name="aColor"> /// . /// </param> private void LogPriority(TaskPriority aTaskPriority, ConsoleColor aColor) { if (PriorityLog == null) { return; } string lPriority = aTaskPriority == TaskPriority.High ? "H" : aTaskPriority == TaskPriority.Normal ? "N" : "L"; PriorityLog.WriteMessage(lPriority, aColor); } #endregion #region Private data /// <summary> /// , /// , , /// . /// </summary> private const int HighPriorityTaskFactor = 3; /// <summary> /// <see cref="IsStopped"/>. /// </summary> private readonly object mIsStoppedLock = new object(); /// <summary> /// . , /// . /// </summary> private readonly ManualResetEvent mPoolStoppedGate = new ManualResetEvent(false); /// <summary> /// , . /// </summary> /// <remarks> /// <see cref="mQueuedTasksLock"/>. /// </remarks> private readonly IList<TaskListEntry> mQueuedTasks = new List<TaskListEntry>(); /// <summary> /// <see cref="mQueuedTasks"/>. /// </summary> private readonly object mQueuedTasksLock = new object(); /// <summary> /// , / . /// </summary> private readonly object mTaskSchedulerLock = new object(); /// <summary> /// , . /// , /// <see cref="HighPriorityTaskFactor"/>. /// </summary> /// <remarks> /// /// <see cref="Interlocked"/>. /// </remarks> private int mQueuedHighPriorityTaskCounter; #endregion #region Nested type: TaskListEntry /// <summary> /// . /// </summary> /// <remarks> /// . /// </remarks> private struct TaskListEntry { #region Constructors /// <summary> /// . /// </summary> /// <param name="aTask"> /// . /// </param> /// <param name="aTaskPriority"> /// . /// </param> public TaskListEntry(Task aTask, TaskPriority aTaskPriority) { mTask = aTask; mTaskPriority = aTaskPriority; } #endregion #region Public properties /// <summary> /// . /// </summary> public Task Task { get { return mTask; } } /// <summary> /// . /// </summary> public TaskPriority TaskPriority { get { return mTaskPriority; } } #endregion #region Private data private readonly Task mTask; private readonly TaskPriority mTaskPriority; #endregion } #endregion } }
// : Eshva.Threading // : Task.cs // GUID : 292467E7-4816-4407-BB9B-3309D13C8614 // : Mike Eshva (mike@eshva.ru) // : 04.06.2012 using System; namespace Eshva.Threading.Framework { /// <summary> /// <see cref="FixedThreadPool"/>. /// </summary> public class Task { #region Constructors /// <summary> /// <see cref="FixedThreadPool"/> /// . /// </summary> /// <param name="aTaskBody"> /// . /// </param> /// <exception cref="ArgumentNullException"> /// . /// </exception> public Task(Action aTaskBody) { if (aTaskBody == null) { throw new ArgumentNullException("aTaskBody", " ."); } TaskBody = aTaskBody; } #endregion #region Public methods /// <summary> /// . /// </summary> public void Execute() { TaskBody(); } #endregion #region Private properties /// <summary> /// / . /// </summary> private Action TaskBody { get; set; } #endregion } }
Source: https://habr.com/ru/post/145551/