diff --git a/STPTests/QueueWorkItemHelper.cs b/STPTests/QueueWorkItemHelper.cs index eb72d14..8a8e3d3 100644 --- a/STPTests/QueueWorkItemHelper.cs +++ b/STPTests/QueueWorkItemHelper.cs @@ -61,7 +61,7 @@ namespace SmartThreadPoolTests wii.WorkItemPriority = WorkItemPriority.AboveNormal; WorkItemInfoComparer wiic = new WorkItemInfoComparer(wii, state); - IWorkItemResult wir = wig.QueueWorkItem(wiic.CompareWorkItemInfo, state, WorkItemPriority.AboveNormal); + IWorkItemResult wir = wig.QueueWorkItem((WorkItemCallback) wiic.CompareWorkItemInfo, state, WorkItemPriority.AboveNormal); bool success = (bool)wir.Result; diff --git a/STPTests/STPTests.csproj b/STPTests/STPTests.csproj index 47334c5..1ffdffc 100644 --- a/STPTests/STPTests.csproj +++ b/STPTests/STPTests.csproj @@ -91,7 +91,10 @@ prompt - + + False + ..\lib\nunit.framework.dll + System diff --git a/SmartThreadPool/Interfaces.cs b/SmartThreadPool/Interfaces.cs index ad8c63f..5b17f2b 100644 --- a/SmartThreadPool/Interfaces.cs +++ b/SmartThreadPool/Interfaces.cs @@ -271,7 +271,19 @@ namespace Amib.Threading /// Queue a work item. /// /// Returns a IWorkItemResult object, but its GetResult() will always return null - IWorkItemResult QueueWorkItem(Action action, T arg); + IWorkItemResult QueueWorkItem (Action action, WorkItemPriority priority); + + /// + /// Queue a work item. + /// + /// Returns a IWorkItemResult object, but its GetResult() will always return null + IWorkItemResult QueueWorkItem (Action action, T arg, WorkItemPriority priority); + + /// + /// Queue a work item. + /// + /// Returns a IWorkItemResult object, but its GetResult() will always return null + IWorkItemResult QueueWorkItem (Action action, T arg); /// /// Queue a work item. @@ -279,18 +291,36 @@ namespace Amib.Threading /// Returns a IWorkItemResult object, but its GetResult() will always return null IWorkItemResult QueueWorkItem(Action action, T1 arg1, T2 arg2); + /// + /// Queue a work item. + /// + /// Returns a IWorkItemResult object, but its GetResult() will always return null + IWorkItemResult QueueWorkItem (Action action, T1 arg1, T2 arg2, WorkItemPriority priority); + /// /// Queue a work item. /// /// Returns a IWorkItemResult object, but its GetResult() will always return null IWorkItemResult QueueWorkItem(Action action, T1 arg1, T2 arg2, T3 arg3); + /// + /// Queue a work item. + /// + /// Returns a IWorkItemResult object, but its GetResult() will always return null + IWorkItemResult QueueWorkItem (Action action, T1 arg1, T2 arg2, T3 arg3, WorkItemPriority priority); + /// /// Queue a work item. /// /// Returns a IWorkItemResult object, but its GetResult() will always return null IWorkItemResult QueueWorkItem(Action action, T1 arg1, T2 arg2, T3 arg3, T4 arg4); + /// + /// Queue a work item. + /// + /// Returns a IWorkItemResult object, but its GetResult() will always return null + IWorkItemResult QueueWorkItem (Action action, T1 arg1, T2 arg2, T3 arg3, T4 arg4, WorkItemPriority priority); + #endregion #region QueueWorkItem(Func<...>) diff --git a/SmartThreadPool/Properties/AssemblyInfo.cs b/SmartThreadPool/Properties/AssemblyInfo.cs index 6f0590b..92b94a1 100644 --- a/SmartThreadPool/Properties/AssemblyInfo.cs +++ b/SmartThreadPool/Properties/AssemblyInfo.cs @@ -12,7 +12,7 @@ using System.Runtime.InteropServices; [assembly: AssemblyCulture("")] [assembly: ComVisible(false)] [assembly: Guid("c764a3de-c4f8-434d-85b5-a09830d1e44f")] -[assembly: AssemblyVersion("2.2.1.0")] +[assembly: AssemblyVersion("2.2.2.0")] [assembly: InternalsVisibleTo("STPTests")] diff --git a/SmartThreadPool/STPStartInfo.cs b/SmartThreadPool/STPStartInfo.cs index c4a8e07..d19a1d9 100644 --- a/SmartThreadPool/STPStartInfo.cs +++ b/SmartThreadPool/STPStartInfo.cs @@ -13,7 +13,9 @@ namespace Amib.Threading private int _maxWorkerThreads = SmartThreadPool.DefaultMaxWorkerThreads; private ThreadPriority _threadPriority = SmartThreadPool.DefaultThreadPriority; private string _performanceCounterInstanceName = SmartThreadPool.DefaultPerformanceCounterInstanceName; + private bool _areThreadsBackground = SmartThreadPool.DefaultAreThreadsBackground; private bool _enableLocalPerformanceCounters; + private string _threadPoolName = SmartThreadPool.DefaultThreadPoolName; public STPStartInfo() { @@ -33,6 +35,8 @@ namespace Amib.Threading _threadPriority = stpStartInfo.ThreadPriority; _performanceCounterInstanceName = stpStartInfo.PerformanceCounterInstanceName; _enableLocalPerformanceCounters = stpStartInfo._enableLocalPerformanceCounters; + _threadPoolName = stpStartInfo._threadPoolName; + _areThreadsBackground = stpStartInfo.AreThreadsBackground; } @@ -93,6 +97,18 @@ namespace Amib.Threading } } + /// + /// Get/Set the thread pool name. Threads will get names depending on this. + /// + public virtual string ThreadPoolName { + get { return _threadPoolName; } + set + { + ThrowIfReadOnly (); + _threadPoolName = value; + } + } + /// /// Get/Set the performance counter instance name of this SmartThreadPool /// The default is null which indicate not to use performance counters at all. @@ -123,6 +139,19 @@ namespace Amib.Threading } } + /// + /// Get/Set backgroundness of thread in thread pool. + /// + public virtual bool AreThreadsBackground + { + get { return _areThreadsBackground; } + set + { + ThrowIfReadOnly (); + _areThreadsBackground = value; + } + } + /// /// Get a readonly version of this STPStartInfo. /// diff --git a/SmartThreadPool/SmartThreadPool.cs b/SmartThreadPool/SmartThreadPool.cs index dab2478..3865d00 100644 --- a/SmartThreadPool/SmartThreadPool.cs +++ b/SmartThreadPool/SmartThreadPool.cs @@ -161,9 +161,19 @@ namespace Amib.Threading /// /// The default fill state with params. (false) + + /// + /// The default thread pool name. (SmartThreadPool) + /// + public const string DefaultThreadPoolName = "SmartThreadPool"; /// It is relevant only to QueueWorkItem of Action<...>/Func<...> /// public const bool DefaultFillStateWithArgs = false; + + /// + /// The default thread backgroundness. (true) + /// + public const bool DefaultAreThreadsBackground = true; #endregion @@ -390,7 +400,7 @@ namespace Amib.Threading private void Initialize() { - Name = "SmartThreadPool"; + Name = _stpStartInfo.ThreadPoolName; ValidateSTPStartInfo(); // _stpStartInfoRW stores a read/write copy of the STPStartInfo. @@ -608,7 +618,7 @@ namespace Amib.Threading // Configure the new thread and start it workerThread.Name = "STP " + Name + " Thread #" + _threadCounter; - workerThread.IsBackground = true; + workerThread.IsBackground = _stpStartInfo.AreThreadsBackground; #if !(_SILVERLIGHT) workerThread.Priority = _stpStartInfo.ThreadPriority; #endif diff --git a/SmartThreadPool/SmartThreadPoolMono.csproj b/SmartThreadPool/SmartThreadPoolMono.csproj index ce4c31f..da81348 100644 --- a/SmartThreadPool/SmartThreadPoolMono.csproj +++ b/SmartThreadPool/SmartThreadPoolMono.csproj @@ -5,7 +5,7 @@ {3462F30B-0156-409C-B256-6046D6F1764B} Library false - SmartThreadPoolMono + SmartThreadPool Amib.Threading @@ -17,16 +17,18 @@ true full false - .\bin\Debug\ + .\bin\Debug\Mono TRACE;DEBUG;_MONO - pdbonly + full true - .\bin\Release\ + bin\Release\Mono\ TRACE;_MONO + bin\Release\Mono\SmartThreadPool.XML + true diff --git a/SmartThreadPool/WorkItemsGroupBase.cs b/SmartThreadPool/WorkItemsGroupBase.cs index 106a1df..27fae5e 100644 --- a/SmartThreadPool/WorkItemsGroupBase.cs +++ b/SmartThreadPool/WorkItemsGroupBase.cs @@ -278,82 +278,110 @@ namespace Amib.Threading.Internal public IWorkItemResult QueueWorkItem(Action action) { - PreQueueWorkItem(); - WorkItem workItem = WorkItemFactory.CreateWorkItem( + return QueueWorkItem (action, SmartThreadPool.DefaultWorkItemPriority); + } + + public IWorkItemResult QueueWorkItem (Action action, WorkItemPriority priority) + { + PreQueueWorkItem (); + WorkItem workItem = WorkItemFactory.CreateWorkItem ( this, WIGStartInfo, delegate { - action.Invoke(); + action.Invoke (); return null; - }); - Enqueue(workItem); - return workItem.GetWorkItemResult(); + }, priority); + Enqueue (workItem); + return workItem.GetWorkItemResult (); } public IWorkItemResult QueueWorkItem(Action action, T arg) { - PreQueueWorkItem(); - WorkItem workItem = WorkItemFactory.CreateWorkItem( + return QueueWorkItem (action, arg, SmartThreadPool.DefaultWorkItemPriority); + } + + public IWorkItemResult QueueWorkItem (Action action, T arg, WorkItemPriority priority) + { + PreQueueWorkItem (); + WorkItem workItem = WorkItemFactory.CreateWorkItem ( this, WIGStartInfo, state => - { - action.Invoke(arg); - return null; - }, - WIGStartInfo.FillStateWithArgs ? new object[] { arg } : null); - Enqueue(workItem); - return workItem.GetWorkItemResult(); + { + action.Invoke (arg); + return null; + }, + WIGStartInfo.FillStateWithArgs ? new object[] { arg } : null, priority); + Enqueue (workItem); + return workItem.GetWorkItemResult (); } public IWorkItemResult QueueWorkItem(Action action, T1 arg1, T2 arg2) { - PreQueueWorkItem(); - WorkItem workItem = WorkItemFactory.CreateWorkItem( + return QueueWorkItem (action, arg1, arg2, SmartThreadPool.DefaultWorkItemPriority); + } + + public IWorkItemResult QueueWorkItem (Action action, T1 arg1, T2 arg2, WorkItemPriority priority) + { + PreQueueWorkItem (); + WorkItem workItem = WorkItemFactory.CreateWorkItem ( this, WIGStartInfo, state => { - action.Invoke(arg1, arg2); + action.Invoke (arg1, arg2); return null; }, - WIGStartInfo.FillStateWithArgs ? new object[] { arg1, arg2 } : null); - Enqueue(workItem); - return workItem.GetWorkItemResult(); + WIGStartInfo.FillStateWithArgs ? new object[] { arg1, arg2 } : null, priority); + Enqueue (workItem); + return workItem.GetWorkItemResult (); } public IWorkItemResult QueueWorkItem(Action action, T1 arg1, T2 arg2, T3 arg3) { - PreQueueWorkItem(); - WorkItem workItem = WorkItemFactory.CreateWorkItem( + return QueueWorkItem (action, arg1, arg2, arg3, SmartThreadPool.DefaultWorkItemPriority); + ; + } + + public IWorkItemResult QueueWorkItem (Action action, T1 arg1, T2 arg2, T3 arg3, WorkItemPriority priority) + { + PreQueueWorkItem (); + WorkItem workItem = WorkItemFactory.CreateWorkItem ( this, WIGStartInfo, state => { - action.Invoke(arg1, arg2, arg3); + action.Invoke (arg1, arg2, arg3); return null; }, - WIGStartInfo.FillStateWithArgs ? new object[] { arg1, arg2, arg3 } : null); - Enqueue(workItem); - return workItem.GetWorkItemResult(); + WIGStartInfo.FillStateWithArgs ? new object[] { arg1, arg2, arg3 } : null, priority); + Enqueue (workItem); + return workItem.GetWorkItemResult (); } public IWorkItemResult QueueWorkItem( Action action, T1 arg1, T2 arg2, T3 arg3, T4 arg4) { - PreQueueWorkItem(); - WorkItem workItem = WorkItemFactory.CreateWorkItem( + return QueueWorkItem (action, arg1, arg2, arg3, arg4, + SmartThreadPool.DefaultWorkItemPriority); + } + + public IWorkItemResult QueueWorkItem ( + Action action, T1 arg1, T2 arg2, T3 arg3, T4 arg4, WorkItemPriority priority) + { + PreQueueWorkItem (); + WorkItem workItem = WorkItemFactory.CreateWorkItem ( this, WIGStartInfo, state => { - action.Invoke(arg1, arg2, arg3, arg4); + action.Invoke (arg1, arg2, arg3, arg4); return null; }, - WIGStartInfo.FillStateWithArgs ? new object[] { arg1, arg2, arg3, arg4 } : null); - Enqueue(workItem); - return workItem.GetWorkItemResult(); + WIGStartInfo.FillStateWithArgs ? new object[] { arg1, arg2, arg3, arg4 } : null, priority); + Enqueue (workItem); + return workItem.GetWorkItemResult (); } #endregion diff --git a/SmartThreadPool/WorkItemsQueue.cs b/SmartThreadPool/WorkItemsQueue.cs index 55642ae..689044a 100644 --- a/SmartThreadPool/WorkItemsQueue.cs +++ b/SmartThreadPool/WorkItemsQueue.cs @@ -163,27 +163,22 @@ namespace Amib.Threading.Internal int millisecondsTimeout, WaitHandle cancelEvent) { - // This method cause the caller to wait for a work item. - // If there is at least one waiting work item then the - // method returns immidiately with it. - // - // If there are no waiting work items then the caller - // is queued between other waiters for a work item to arrive. - // - // If a work item didn't come within millisecondsTimeout or - // the user canceled the wait by signaling the cancelEvent - // then the method returns null to indicate that the caller - // didn't get a work item. - - WaiterEntry waiterEntry; - WorkItem workItem = null; - - lock (this) - { - //Stopwatch stopwatch = Stopwatch.StartNew(); - //Monitor.Enter(this); - //stopwatch.Stop(); + // This method cause the caller to wait for a work item. + // If there is at least one waiting work item then the + // method returns immidiately with it. + // + // If there are no waiting work items then the caller + // is queued between other waiters for a work item to arrive. + // + // If a work item didn't come within millisecondsTimeout or + // the user canceled the wait by signaling the cancelEvent + // then the method returns null to indicate that the caller + // didn't get a work item. + WaiterEntry waiterEntry; + WorkItem workItem = null; + lock (this) + { ValidateNotDisposed(); // If there are waiting work items then take one and return. @@ -200,7 +195,7 @@ namespace Amib.Threading.Internal // Put the waiter with the other waiters PushWaiter(waiterEntry); - } + } // Prepare array of wait handle for the WaitHandle.WaitAny() WaitHandle [] waitHandles = new WaitHandle[] { diff --git a/WorkItemsGroupDemo/Form1.cs b/WorkItemsGroupDemo/Form1.cs index f298d49..3dce606 100644 --- a/WorkItemsGroupDemo/Form1.cs +++ b/WorkItemsGroupDemo/Form1.cs @@ -294,7 +294,7 @@ namespace WorkItemsGroupDemo spinIdleTimeout.Enabled = !start; } - private object DoNothing(object state) + private void DoNothing(WorkItemState state) { WorkItemState workItemState = (WorkItemState)state; _workingStates.Add(workItemState.QueueUsageEntry, workItemState.QueueUsageEntry); @@ -310,7 +310,7 @@ namespace WorkItemsGroupDemo } while (_paused); _workingStates.Remove(workItemState.QueueUsageEntry); - return null; + //return null; }