Browse Source

some changes on Dispose

UbitUmarov 3 years ago
parent
commit
592b94d142

+ 2 - 7
OpenSim/Capabilities/Caps.cs

@@ -158,12 +158,7 @@ namespace OpenSim.Framework.Capabilities
 
         ~Caps()
         {
-            Flags = CapsFlags.None;
-            if (m_capsActive!= null)
-            {
-                m_capsActive.Dispose();
-                m_capsActive = null;
-            }
+            Dispose(false);
         }
         
         public void Dispose()
@@ -172,7 +167,7 @@ namespace OpenSim.Framework.Capabilities
             GC.SuppressFinalize(this);
         }
 
-        public void Dispose(bool disposing)
+        protected void Dispose(bool disposing)
         {
             Flags = CapsFlags.None;
             if (m_capsActive != null)

+ 1 - 1
OpenSim/Framework/ExpiringKey.cs

@@ -88,7 +88,7 @@ namespace OpenSim.Framework
             GC.SuppressFinalize(this);
         }
 
-        public void Dispose(bool disposing)
+        protected void Dispose(bool disposing)
         {
             if (m_rwLock != null)
             {

+ 1 - 1
OpenSim/Framework/Servers/HttpServer/OSHttpServer/HttpClientContext.cs

@@ -727,7 +727,7 @@ namespace OSHttpServer
             GC.SuppressFinalize(this);
         }
 
-        public void Dispose(bool disposing)
+        protected void Dispose(bool disposing)
         {
             if (contextID >= 0)
             {

+ 1 - 1
OpenSim/Framework/Servers/HttpServer/OSHttpServer/HttpListener.cs

@@ -242,7 +242,7 @@ namespace OSHttpServer
             GC.SuppressFinalize(this);
         }
 
-        public void Dispose(bool disposing)
+        protected void Dispose(bool disposing)
         {
             if (m_shutdownEvent != null)
             {

+ 98 - 94
ThirdParty/SmartThreadPool/SmartThreadPool.cs

@@ -3,68 +3,68 @@
 // Smart Thread Pool
 // 7 Aug 2004 - Initial release
 //
-// 14 Sep 2004 - Bug fixes
+// 14 Sep 2004 - Bug fixes 
 //
 // 15 Oct 2004 - Added new features
-//		- Work items return result.
-//		- Support waiting synchronization for multiple work items.
-//		- Work items can be cancelled.
-//		- Passage of the caller thread’s context to the thread in the pool.
-//		- Minimal usage of WIN32 handles.
-//		- Minor bug fixes.
+//        - Work items return result.
+//        - Support waiting synchronization for multiple work items.
+//        - Work items can be cancelled.
+//        - Passage of the caller thread’s context to the thread in the pool.
+//        - Minimal usage of WIN32 handles.
+//        - Minor bug fixes.
 //
 // 26 Dec 2004 - Changes:
-//		- Removed static constructors.
+//        - Removed static constructors.
 //      - Added finalizers.
-//		- Changed Exceptions so they are serializable.
-//		- Fixed the bug in one of the SmartThreadPool constructors.
-//		- Changed the SmartThreadPool.WaitAll() so it will support any number of waiters.
+//        - Changed Exceptions so they are serializable.
+//        - Fixed the bug in one of the SmartThreadPool constructors.
+//        - Changed the SmartThreadPool.WaitAll() so it will support any number of waiters. 
 //        The SmartThreadPool.WaitAny() is still limited by the .NET Framework.
-//		- Added PostExecute with options on which cases to call it.
+//        - Added PostExecute with options on which cases to call it.
 //      - Added option to dispose of the state objects.
 //      - Added a WaitForIdle() method that waits until the work items queue is empty.
 //      - Added an STPStartInfo class for the initialization of the thread pool.
-//      - Changed exception handling so if a work item throws an exception it
+//      - Changed exception handling so if a work item throws an exception it 
 //        is rethrown at GetResult(), rather then firing an UnhandledException event.
 //        Note that PostExecute exception are always ignored.
 //
 // 25 Mar 2005 - Changes:
-//		- Fixed lost of work items bug
+//        - Fixed lost of work items bug
 //
 // 3 Jul 2005: Changes.
-//      - Fixed bug where Enqueue() throws an exception because PopWaiter() returned null, hardly reconstructed.
+//      - Fixed bug where Enqueue() throws an exception because PopWaiter() returned null, hardly reconstructed. 
 //
 // 16 Aug 2005: Changes.
-//		- Fixed bug where the InUseThreads becomes negative when canceling work items.
+//        - Fixed bug where the InUseThreads becomes negative when canceling work items. 
 //
 // 31 Jan 2006 - Changes:
-//		- Added work items priority
-//		- Removed support of chained delegates in callbacks and post executes (nobody really use this)
-//		- Added work items groups
-//		- Added work items groups idle event
-//		- Changed SmartThreadPool.WaitAll() behavior so when it gets empty array
-//		  it returns true rather then throwing an exception.
-//		- Added option to start the STP and the WIG as suspended
-//		- Exception behavior changed, the real exception is returned by an
-//		  inner exception
-//		- Added option to keep the Http context of the caller thread. (Thanks to Steven T.)
-//		- Added performance counters
-//		- Added priority to the threads in the pool
+//        - Added work items priority
+//        - Removed support of chained delegates in callbacks and post executes (nobody really use this)
+//        - Added work items groups
+//        - Added work items groups idle event
+//        - Changed SmartThreadPool.WaitAll() behavior so when it gets empty array
+//          it returns true rather then throwing an exception.
+//        - Added option to start the STP and the WIG as suspended
+//        - Exception behavior changed, the real exception is returned by an 
+//          inner exception
+//        - Added option to keep the Http context of the caller thread. (Thanks to Steven T.)
+//        - Added performance counters
+//        - Added priority to the threads in the pool
 //
 // 13 Feb 2006 - Changes:
-//		- Added a call to the dispose of the Performance Counter so
-//		  their won't be a Performance Counter leak.
-//		- Added exception catch in case the Performance Counters cannot
-//		  be created.
+//        - Added a call to the dispose of the Performance Counter so
+//          their won't be a Performance Counter leak.
+//        - Added exception catch in case the Performance Counters cannot 
+//          be created.
 //
 // 17 May 2008 - Changes:
 //      - Changed the dispose behavior and removed the Finalizers.
 //      - Enabled the change of the MaxThreads and MinThreads at run time.
-//      - Enabled the change of the Concurrency of a IWorkItemsGroup at run
-//        time If the IWorkItemsGroup is a SmartThreadPool then the Concurrency
-//        refers to the MaxThreads.
+//      - Enabled the change of the Concurrency of a IWorkItemsGroup at run 
+//        time If the IWorkItemsGroup is a SmartThreadPool then the Concurrency 
+//        refers to the MaxThreads. 
 //      - Improved the cancel behavior.
-//      - Added events for thread creation and termination.
+//      - Added events for thread creation and termination. 
 //      - Fixed the HttpContext context capture.
 //      - Changed internal collections so they use generic collections
 //      - Added IsIdle flag to the SmartThreadPool and IWorkItemsGroup
@@ -83,7 +83,7 @@
 //
 // 20 August 2012 - Changes:
 //      - Added set name to threads
-//      - Fixed the WorkItemsQueue.Dequeue.
+//      - Fixed the WorkItemsQueue.Dequeue. 
 //        Replaced while (!Monitor.TryEnter(this)); with lock(this) { ... }
 //      - Fixed SmartThreadPool.Pipe
 //      - Added IsBackground option to threads
@@ -92,7 +92,7 @@
 //
 // 24 August 2012 - Changes:
 //      - Enabled cancel abort after cancel. See: http://smartthreadpool.codeplex.com/discussions/345937 by alecswan
-//      - Added option to set MaxStackSize of threads
+//      - Added option to set MaxStackSize of threads 
 
 #endregion
 
@@ -129,7 +129,7 @@ namespace Amib.Threading
         /// <summary>
         /// Default idle timeout in milliseconds. (One minute)
         /// </summary>
-        public const int DefaultIdleTimeout = 60*1000; // One minute
+        public const int DefaultIdleTimeout = 60 * 1000; // One minute
 
         /// <summary>
         /// Indicate to copy the security context of the caller and then use it in the call. (false)
@@ -203,8 +203,8 @@ namespace Amib.Threading
 
 #if !(_SILVERLIGHT) && !(WINDOWS_PHONE)
         /// <summary>
-        /// The default apartment state of a thread in the thread pool.
-        /// The default is ApartmentState.Unknown which means the STP will not
+        /// The default apartment state of a thread in the thread pool. 
+        /// The default is ApartmentState.Unknown which means the STP will not 
         /// set the apartment of the thread. It will use the .NET default.
         /// </summary>
         public const ApartmentState DefaultApartmentState = ApartmentState.Unknown;
@@ -242,7 +242,7 @@ namespace Amib.Threading
         private STPStartInfo _stpStartInfo;
 
         /// <summary>
-        /// Total number of work items that are stored in the work items queue
+        /// Total number of work items that are stored in the work items queue 
         /// plus the work items that the threads in the pool are working on.
         /// </summary>
         private int _currentWorkItemsCount;
@@ -282,7 +282,7 @@ namespace Amib.Threading
         private bool _isDisposed;
 
         /// <summary>
-        /// Holds all the WorkItemsGroup instaces that have at least one
+        /// Holds all the WorkItemsGroup instaces that have at least one 
         /// work item int the SmartThreadPool
         /// This variable is used in case of Shutdown
         /// </summary>
@@ -305,7 +305,7 @@ namespace Amib.Threading
         private ISTPInstancePerformanceCounters _localPCs = NullSTPInstancePerformanceCounters.Instance;
 
 
-#if (WINDOWS_PHONE)
+#if (WINDOWS_PHONE) 
         private static readonly Dictionary<int, ThreadEntry> _threadEntries = new Dictionary<int, ThreadEntry>();
 #elif (_WINDOWS_CE)
         private static LocalDataStoreSlot _threadEntrySlot = Thread.AllocateDataSlot();
@@ -316,13 +316,13 @@ namespace Amib.Threading
 #endif
 
         /// <summary>
-        /// An event to call after a thread is created, but before
+        /// An event to call after a thread is created, but before 
         /// it's first use.
         /// </summary>
         private event ThreadInitializationHandler _onThreadInitialization;
 
         /// <summary>
-        /// An event to call when a thread is about to exit, after
+        /// An event to call when a thread is about to exit, after 
         /// it is no longer belong to the pool.
         /// </summary>
         private event ThreadTerminationHandler _onThreadTermination;
@@ -332,7 +332,7 @@ namespace Amib.Threading
         #region Per thread properties
 
         /// <summary>
-        /// A reference to the current work item a thread from the thread pool
+        /// A reference to the current work item a thread from the thread pool 
         /// is executing.
         /// </summary>
         internal static ThreadEntry CurrentThreadEntry
@@ -528,7 +528,7 @@ namespace Amib.Threading
 
         private static void ValidateCallback(Delegate callback)
         {
-            if(callback.GetInvocationList().Length > 1)
+            if (callback.GetInvocationList().Length > 1)
             {
                 throw new NotSupportedException("SmartThreadPool doesn't support delegates chains");
             }
@@ -628,7 +628,7 @@ namespace Amib.Threading
         /// </summary>
         private void InformCompleted()
         {
-            // There is no need to lock the two methods together
+            // There is no need to lock the two methods together 
             // since only the current thread removes itself
             // and the _workerThreads is a synchronized dictionary
             if (_workerThreads.Contains(Thread.CurrentThread))
@@ -650,7 +650,7 @@ namespace Amib.Threading
                 return;
             }
 
-            lock(_workerThreads.SyncRoot)
+            lock (_workerThreads.SyncRoot)
             {
                 // Don't start threads on shut down
                 if (_shutdown)
@@ -658,7 +658,7 @@ namespace Amib.Threading
                     return;
                 }
 
-                for(int i = 0; i < threadsCount; ++i)
+                for (int i = 0; i < threadsCount; ++i)
                 {
                     // Don't create more threads then the upper limit
                     if (_workerThreads.Count >= _stpStartInfo.MaxWorkerThreads)
@@ -719,7 +719,7 @@ namespace Amib.Threading
                 bool bInUseWorkerThreadsWasIncremented = false;
 
                 // Process until shutdown.
-                while(!_shutdown)
+                while (!_shutdown)
                 {
                     // Update the last time this thread was seen alive.
                     // It's good for debugging.
@@ -757,7 +757,7 @@ namespace Amib.Threading
                         // Double lock for quit.
                         if (_workerThreads.Count > _stpStartInfo.MinWorkerThreads)
                         {
-                            lock(_workerThreads.SyncRoot)
+                            lock (_workerThreads.SyncRoot)
                             {
                                 if (_workerThreads.Count > _stpStartInfo.MinWorkerThreads)
                                 {
@@ -784,19 +784,19 @@ namespace Amib.Threading
                         bInUseWorkerThreadsWasIncremented = false;
 
                         // Set the Current Work Item of the thread.
-                        // Store the Current Work Item  before the workItem.StartingWorkItem() is called,
-                        // so WorkItem.Cancel can work when the work item is between InQueue and InProgress
+                        // Store the Current Work Item  before the workItem.StartingWorkItem() is called, 
+                        // so WorkItem.Cancel can work when the work item is between InQueue and InProgress 
                         // states.
-                        // If the work item has been cancelled BEFORE the workItem.StartingWorkItem()
+                        // If the work item has been cancelled BEFORE the workItem.StartingWorkItem() 
                         // (work item is in InQueue state) then workItem.StartingWorkItem() will return false.
                         // If the work item has been cancelled AFTER the workItem.StartingWorkItem() then
                         // (work item is in InProgress state) then the thread will be aborted
                         CurrentThreadEntry.CurrentWorkItem = workItem;
 
                         // Change the state of the work item to 'in progress' if possible.
-                        // We do it here so if the work item has been canceled we won't
+                        // We do it here so if the work item has been canceled we won't 
                         // increment the _inUseWorkerThreads.
-                        // The cancel mechanism doesn't delete items from the queue,
+                        // The cancel mechanism doesn't delete items from the queue,  
                         // it marks the work item as canceled, and when the work item
                         // is dequeued, we just skip it.
                         // If the post execute of work item is set to always or to
@@ -821,7 +821,7 @@ namespace Amib.Threading
 
                         ExecuteWorkItem(workItem);
                     }
-                    catch(Exception ex)
+                    catch (Exception ex)
                     {
                         ex.GetHashCode();
                         // Do nothing
@@ -830,11 +830,11 @@ namespace Amib.Threading
                     {
                         workItem.DisposeOfState();
 
-                        // Set the CurrentWorkItem to null, since we
+                        // Set the CurrentWorkItem to null, since we 
                         // no longer run user's code.
                         CurrentThreadEntry.CurrentWorkItem = null;
 
-                        // Decrement the _inUseWorkerThreads only if we had
+                        // Decrement the _inUseWorkerThreads only if we had 
                         // incremented it. Note the cancelled work items don't
                         // increment _inUseWorkerThreads.
                         if (bInUseWorkerThreadsWasIncremented)
@@ -848,13 +848,13 @@ namespace Amib.Threading
                         // WorkItemsGroup may enqueue their next work item.
                         workItem.FireWorkItemCompleted();
 
-                        // Decrement the number of work items here so the idle
+                        // Decrement the number of work items here so the idle 
                         // ManualResetEvent won't fluctuate.
                         DecrementWorkItemsCount();
                     }
                 }
             }
-            catch(ThreadAbortException tae)
+            catch (ThreadAbortException tae)
             {
                 tae.GetHashCode();
                 // Handle the abort exception gracfully.
@@ -862,7 +862,7 @@ namespace Amib.Threading
                 Thread.ResetAbort();
 #endif
             }
-            catch(Exception e)
+            catch (Exception e)
             {
                 Debug.Assert(null != e);
             }
@@ -964,8 +964,8 @@ namespace Amib.Threading
                 pcs.Dispose();
             }
 
-            Thread [] threads;
-            lock(_workerThreads.SyncRoot)
+            Thread[] threads;
+            lock (_workerThreads.SyncRoot)
             {
                 // Shutdown the work items queue
                 _workItemsQueue.Dispose();
@@ -975,7 +975,7 @@ namespace Amib.Threading
                 _shuttingDownEvent.Set();
 
                 // Make a copy of the threads' references in the pool
-                threads = new Thread [_workerThreads.Count];
+                threads = new Thread[_workerThreads.Count];
                 _workerThreads.Keys.CopyTo(threads, 0);
             }
 
@@ -986,7 +986,7 @@ namespace Amib.Threading
             bool timeout = false;
 
             // Each iteration we update the time left for the timeout.
-            foreach(Thread thread in threads)
+            foreach (Thread thread in threads)
             {
                 // Join don't work with negative numbers
                 if (!waitInfinitely && (millisecondsLeft < 0))
@@ -997,13 +997,13 @@ namespace Amib.Threading
 
                 // Wait for the thread to terminate
                 bool success = thread.Join(millisecondsLeft);
-                if(!success)
+                if (!success)
                 {
                     timeout = true;
                     break;
                 }
 
-                if(!waitInfinitely)
+                if (!waitInfinitely)
                 {
                     // Update the time left to wait
                     //TimeSpan ts = DateTime.UtcNow - start;
@@ -1014,27 +1014,27 @@ namespace Amib.Threading
             if (timeout && forceAbort)
             {
                 // Abort the threads in the pool
-                foreach(Thread thread in threads)
+                foreach (Thread thread in threads)
                 {
 
                     if ((thread != null)
 #if !(_WINDOWS_CE)
                         && thread.IsAlive
-#endif
+#endif                        
                         )
                     {
                         try
                         {
                             thread.Abort(); // Shutdown
                         }
-                        catch(SecurityException e)
+                        catch (SecurityException e)
                         {
                             e.GetHashCode();
                         }
-                        catch(ThreadStateException ex)
+                        catch (ThreadStateException ex)
                         {
                             ex.GetHashCode();
-                            // In case the thread has been terminated
+                            // In case the thread has been terminated 
                             // after the check if it is alive.
                         }
                     }
@@ -1050,7 +1050,7 @@ namespace Amib.Threading
         /// true when every work item in workItemResults has completed; otherwise false.
         /// </returns>
         public static bool WaitAll(
-            IWaitableResult [] waitableResults)
+            IWaitableResult[] waitableResults)
         {
             return WaitAll(waitableResults, Timeout.Infinite, true);
         }
@@ -1061,13 +1061,13 @@ namespace Amib.Threading
         /// <param name="waitableResults">Array of work item result objects</param>
         /// <param name="timeout">The number of milliseconds to wait, or a TimeSpan that represents -1 milliseconds to wait indefinitely. </param>
         /// <param name="exitContext">
-        /// true to exit the synchronization domain for the context before the wait (if in a synchronized context), and reacquire it; otherwise, false.
+        /// true to exit the synchronization domain for the context before the wait (if in a synchronized context), and reacquire it; otherwise, false. 
         /// </param>
         /// <returns>
         /// true when every work item in workItemResults has completed; otherwise false.
         /// </returns>
         public static bool WaitAll(
-            IWaitableResult [] waitableResults,
+            IWaitableResult[] waitableResults,
             TimeSpan timeout,
             bool exitContext)
         {
@@ -1080,7 +1080,7 @@ namespace Amib.Threading
         /// <param name="waitableResults">Array of work item result objects</param>
         /// <param name="timeout">The number of milliseconds to wait, or a TimeSpan that represents -1 milliseconds to wait indefinitely. </param>
         /// <param name="exitContext">
-        /// true to exit the synchronization domain for the context before the wait (if in a synchronized context), and reacquire it; otherwise, false.
+        /// true to exit the synchronization domain for the context before the wait (if in a synchronized context), and reacquire it; otherwise, false. 
         /// </param>
         /// <param name="cancelWaitHandle">A cancel wait handle to interrupt the wait if needed</param>
         /// <returns>
@@ -1101,13 +1101,13 @@ namespace Amib.Threading
         /// <param name="waitableResults">Array of work item result objects</param>
         /// <param name="millisecondsTimeout">The number of milliseconds to wait, or Timeout.Infinite (-1) to wait indefinitely.</param>
         /// <param name="exitContext">
-        /// true to exit the synchronization domain for the context before the wait (if in a synchronized context), and reacquire it; otherwise, false.
+        /// true to exit the synchronization domain for the context before the wait (if in a synchronized context), and reacquire it; otherwise, false. 
         /// </param>
         /// <returns>
         /// true when every work item in workItemResults has completed; otherwise false.
         /// </returns>
         public static bool WaitAll(
-            IWaitableResult [] waitableResults,
+            IWaitableResult[] waitableResults,
             int millisecondsTimeout,
             bool exitContext)
         {
@@ -1120,7 +1120,7 @@ namespace Amib.Threading
         /// <param name="waitableResults">Array of work item result objects</param>
         /// <param name="millisecondsTimeout">The number of milliseconds to wait, or Timeout.Infinite (-1) to wait indefinitely.</param>
         /// <param name="exitContext">
-        /// true to exit the synchronization domain for the context before the wait (if in a synchronized context), and reacquire it; otherwise, false.
+        /// true to exit the synchronization domain for the context before the wait (if in a synchronized context), and reacquire it; otherwise, false. 
         /// </param>
         /// <param name="cancelWaitHandle">A cancel wait handle to interrupt the wait if needed</param>
         /// <returns>
@@ -1144,7 +1144,7 @@ namespace Amib.Threading
         /// The array index of the work item result that satisfied the wait, or WaitTimeout if any of the work items has been canceled.
         /// </returns>
         public static int WaitAny(
-            IWaitableResult [] waitableResults)
+            IWaitableResult[] waitableResults)
         {
             return WaitAny(waitableResults, Timeout.Infinite, true);
         }
@@ -1155,7 +1155,7 @@ namespace Amib.Threading
         /// <param name="waitableResults">Array of work item result objects</param>
         /// <param name="timeout">The number of milliseconds to wait, or a TimeSpan that represents -1 milliseconds to wait indefinitely. </param>
         /// <param name="exitContext">
-        /// true to exit the synchronization domain for the context before the wait (if in a synchronized context), and reacquire it; otherwise, false.
+        /// true to exit the synchronization domain for the context before the wait (if in a synchronized context), and reacquire it; otherwise, false. 
         /// </param>
         /// <returns>
         /// The array index of the work item result that satisfied the wait, or WaitTimeout if no work item result satisfied the wait and a time interval equivalent to millisecondsTimeout has passed or the work item has been canceled.
@@ -1174,14 +1174,14 @@ namespace Amib.Threading
         /// <param name="waitableResults">Array of work item result objects</param>
         /// <param name="timeout">The number of milliseconds to wait, or a TimeSpan that represents -1 milliseconds to wait indefinitely. </param>
         /// <param name="exitContext">
-        /// true to exit the synchronization domain for the context before the wait (if in a synchronized context), and reacquire it; otherwise, false.
+        /// true to exit the synchronization domain for the context before the wait (if in a synchronized context), and reacquire it; otherwise, false. 
         /// </param>
         /// <param name="cancelWaitHandle">A cancel wait handle to interrupt the wait if needed</param>
         /// <returns>
         /// The array index of the work item result that satisfied the wait, or WaitTimeout if no work item result satisfied the wait and a time interval equivalent to millisecondsTimeout has passed or the work item has been canceled.
         /// </returns>
         public static int WaitAny(
-            IWaitableResult [] waitableResults,
+            IWaitableResult[] waitableResults,
             TimeSpan timeout,
             bool exitContext,
             WaitHandle cancelWaitHandle)
@@ -1195,13 +1195,13 @@ namespace Amib.Threading
         /// <param name="waitableResults">Array of work item result objects</param>
         /// <param name="millisecondsTimeout">The number of milliseconds to wait, or Timeout.Infinite (-1) to wait indefinitely.</param>
         /// <param name="exitContext">
-        /// true to exit the synchronization domain for the context before the wait (if in a synchronized context), and reacquire it; otherwise, false.
+        /// true to exit the synchronization domain for the context before the wait (if in a synchronized context), and reacquire it; otherwise, false. 
         /// </param>
         /// <returns>
         /// The array index of the work item result that satisfied the wait, or WaitTimeout if no work item result satisfied the wait and a time interval equivalent to millisecondsTimeout has passed or the work item has been canceled.
         /// </returns>
         public static int WaitAny(
-            IWaitableResult [] waitableResults,
+            IWaitableResult[] waitableResults,
             int millisecondsTimeout,
             bool exitContext)
         {
@@ -1214,14 +1214,14 @@ namespace Amib.Threading
         /// <param name="waitableResults">Array of work item result objects</param>
         /// <param name="millisecondsTimeout">The number of milliseconds to wait, or Timeout.Infinite (-1) to wait indefinitely.</param>
         /// <param name="exitContext">
-        /// true to exit the synchronization domain for the context before the wait (if in a synchronized context), and reacquire it; otherwise, false.
+        /// true to exit the synchronization domain for the context before the wait (if in a synchronized context), and reacquire it; otherwise, false. 
         /// </param>
         /// <param name="cancelWaitHandle">A cancel wait handle to interrupt the wait if needed</param>
         /// <returns>
         /// The array index of the work item result that satisfied the wait, or WaitTimeout if no work item result satisfied the wait and a time interval equivalent to millisecondsTimeout has passed or the work item has been canceled.
         /// </returns>
         public static int WaitAny(
-            IWaitableResult [] waitableResults,
+            IWaitableResult[] waitableResults,
             int millisecondsTimeout,
             bool exitContext,
             WaitHandle cancelWaitHandle)
@@ -1447,7 +1447,7 @@ namespace Amib.Threading
 
         public bool IsShuttingdown
         {
-            get { return _shutdown;  }
+            get { return _shutdown; }
         }
 
         /// <summary>
@@ -1464,6 +1464,12 @@ namespace Amib.Threading
         #region IDisposable Members
 
         public void Dispose()
+        {
+            Dispose(true);
+            GC.SuppressFinalize(this);
+        }
+
+        protected void Dispose(bool disposing)
         {
             if (!_isDisposed)
             {
@@ -1494,7 +1500,7 @@ namespace Amib.Threading
 
         private void ValidateNotDisposed()
         {
-            if(_isDisposed)
+            if (_isDisposed)
             {
                 throw new ObjectDisposedException(GetType().ToString(), "The SmartThreadPool has been shutdown");
             }
@@ -1612,12 +1618,10 @@ namespace Amib.Threading
         {
             add
             {
-                throw new NotImplementedException("This event is not implemented in the SmartThreadPool class. Please create a WorkItemsGroup in order to use this feature.");
                 //_onIdle += value;
             }
             remove
             {
-                throw new NotImplementedException("This event is not implemented in the SmartThreadPool class. Please create a WorkItemsGroup in order to use this feature.");
                 //_onIdle -= value;
             }
         }

+ 47 - 41
ThirdParty/SmartThreadPool/WorkItemsQueue.cs

@@ -34,7 +34,7 @@ namespace Amib.Threading.Internal
         private bool _isWorkItemsQueueActive = true;
 
 
-#if (WINDOWS_PHONE)
+#if (WINDOWS_PHONE) 
         private static readonly Dictionary<int, WaiterEntry> _waiterEntries = new Dictionary<int, WaiterEntry>();
 #elif (_WINDOWS_CE)
         private static LocalDataStoreSlot _waiterEntrySlot = Thread.AllocateDataSlot();
@@ -50,7 +50,7 @@ namespace Amib.Threading.Internal
         /// </summary>
         private static WaiterEntry CurrentWaiterEntry
         {
-#if (WINDOWS_PHONE)
+#if (WINDOWS_PHONE) 
             get
             {
                 lock (_waiterEntries)
@@ -92,8 +92,8 @@ namespace Amib.Threading.Internal
         }
 
         /// <summary>
-        /// A flag that indicates if the WorkItemsQueue has been disposed.
-        /// </summary>
+		/// A flag that indicates if the WorkItemsQueue has been disposed.
+		/// </summary>
         private bool _isDisposed = false;
 
         #endregion
@@ -136,15 +136,15 @@ namespace Amib.Threading.Internal
             // WaitForWorkItem() method to indicate timeout or cancel
             if (null == workItem)
             {
-                throw new ArgumentNullException("workItem" , "workItem cannot be null");
+                throw new ArgumentNullException("workItem", "workItem cannot be null");
             }
 
             bool enqueue = true;
 
-            // First check if there is a waiter waiting for work item. During
-            // the check, timed out waiters are ignored. If there is no
+            // First check if there is a waiter waiting for work item. During 
+            // the check, timed out waiters are ignored. If there is no 
             // waiter then the work item is queued.
-            lock(this)
+            lock (this)
             {
                 ValidateNotDisposed();
 
@@ -153,7 +153,7 @@ namespace Amib.Threading.Internal
                     return false;
                 }
 
-                while(_waitersCount > 0)
+                while (_waitersCount > 0)
                 {
                     // Dequeue a waiter.
                     WaiterEntry waiterEntry = PopWaiter();
@@ -187,15 +187,15 @@ namespace Amib.Threading.Internal
             WaitHandle cancelEvent)
         {
             // This method cause the caller to wait for a work item.
-            // If there is at least one waiting work item then the
+            // 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
+            // 
+            // 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
+            // 
+            // 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;
@@ -221,15 +221,15 @@ namespace Amib.Threading.Internal
             }
 
             // Prepare array of wait handle for the WaitHandle.WaitAny()
-            WaitHandle [] waitHandles = new WaitHandle[] {
+            WaitHandle[] waitHandles = new WaitHandle[] {
                                                                 waiterEntry.WaitHandle,
                                                                 cancelEvent };
 
             // Wait for an available resource, cancel event, or timeout.
 
-            // During the wait we are supposes to exit the synchronization
+            // During the wait we are supposes to exit the synchronization 
             // domain. (Placing true as the third argument of the WaitAny())
-            // It just doesn't work, I don't know why, so I have two lock(this)
+            // It just doesn't work, I don't know why, so I have two lock(this) 
             // statments instead of one.
 
             int index = STPEventWaitHandle.WaitAny(
@@ -237,7 +237,7 @@ namespace Amib.Threading.Internal
                 millisecondsTimeout,
                 true);
 
-            lock(this)
+            lock (this)
             {
                 // success is true if it got a work item.
                 bool success = (0 == index);
@@ -254,7 +254,7 @@ namespace Amib.Threading.Internal
 
                     // On timeout remove the waiter from the queue.
                     // Note that the complexity is O(1).
-                    if(timeout)
+                    if (timeout)
                     {
                         RemoveWaiter(waiterEntry, false);
                     }
@@ -279,12 +279,12 @@ namespace Amib.Threading.Internal
         }
 
         /// <summary>
-        /// Cleanup the work items queue, hence no more work
+        /// Cleanup the work items queue, hence no more work 
         /// items are allowed to be queue
         /// </summary>
         private void Cleanup()
         {
-            lock(this)
+            lock (this)
             {
                 // Deactivate only once
                 if (!_isWorkItemsQueueActive)
@@ -295,7 +295,7 @@ namespace Amib.Threading.Internal
                 // Don't queue more work items
                 _isWorkItemsQueueActive = false;
 
-                foreach(WorkItem workItem in _workItems)
+                foreach (WorkItem workItem in _workItems)
                 {
                     workItem.DisposeOfState();
                 }
@@ -303,15 +303,15 @@ namespace Amib.Threading.Internal
                 // Clear the work items that are already queued
                 _workItems.Clear();
 
-                // Note:
-                // I don't iterate over the queue and dispose of work items's states,
-                // since if a work item has a state object that is still in use in the
+                // Note: 
+                // I don't iterate over the queue and dispose of work items's states, 
+                // since if a work item has a state object that is still in use in the 
                 // application then I must not dispose it.
 
                 // Tell the waiters that they were timed out.
                 // It won't signal them to exit, but to ignore their
                 // next work item.
-                while(_waitersCount > 0)
+                while (_waitersCount > 0)
                 {
                     WaiterEntry waiterEntry = PopWaiter();
                     waiterEntry.Timeout();
@@ -362,18 +362,18 @@ namespace Amib.Threading.Internal
         /// <param name="newWaiterEntry">A waiter to put in the stack</param>
         public void PushWaiter(WaiterEntry newWaiterEntry)
         {
-            // Remove the waiter if it is already in the stack and
+            // Remove the waiter if it is already in the stack and 
             // update waiter's count as needed
             RemoveWaiter(newWaiterEntry, false);
 
-            // If the stack is empty then newWaiterEntry is the new head of the stack
+            // If the stack is empty then newWaiterEntry is the new head of the stack 
             if (null == _headWaiterEntry._nextWaiterEntry)
             {
                 _headWaiterEntry._nextWaiterEntry = newWaiterEntry;
                 newWaiterEntry._prevWaiterEntry = _headWaiterEntry;
 
             }
-            // If the stack is not empty then put newWaiterEntry as the new head
+            // If the stack is not empty then put newWaiterEntry as the new head 
             // of the stack.
             else
             {
@@ -470,7 +470,7 @@ namespace Amib.Threading.Internal
 
         #endregion
 
-        #region WaiterEntry class
+        #region WaiterEntry class 
 
         // A waiter entry in the _waiters queue.
         public sealed class WaiterEntry : IDisposable
@@ -484,21 +484,21 @@ namespace Amib.Threading.Internal
             private AutoResetEvent _waitHandle = EventWaitHandleFactory.CreateAutoResetEvent();
 
             /// <summary>
-            /// Flag to know if this waiter already quited from the queue
+            /// Flag to know if this waiter already quited from the queue 
             /// because of a timeout.
             /// </summary>
             private bool _isTimedout = false;
 
             /// <summary>
-            /// Flag to know if the waiter was signaled and got a work item.
+            /// Flag to know if the waiter was signaled and got a work item. 
             /// </summary>
             private bool _isSignaled = false;
 
             /// <summary>
-            /// A work item that passed directly to the waiter withou going
+            /// A work item that passed directly to the waiter withou going 
             /// through the queue
             /// </summary>
-            private WorkItem _workItem = null;
+			private WorkItem _workItem = null;
 
             private bool _isDisposed = false;
 
@@ -539,7 +539,7 @@ namespace Amib.Threading.Internal
             /// The method fails if Timeout() preceded its call
             public bool Signal(WorkItem workItem)
             {
-                lock(this)
+                lock (this)
                 {
                     if (!_isTimedout)
                     {
@@ -559,13 +559,13 @@ namespace Amib.Threading.Internal
             /// The method fails if Signal() preceded its call
             public bool Timeout()
             {
-                lock(this)
+                lock (this)
                 {
                     // Time out can happen only if the waiter wasn't marked as
                     // signaled
                     if (!_isSignaled)
                     {
-                        // We don't remove the waiter from the queue, the DequeueWorkItem
+                        // We don't remove the waiter from the queue, the DequeueWorkItem 
                         // method skips _waiters that were timed out.
                         _isTimedout = true;
                         return true;
@@ -621,18 +621,24 @@ namespace Amib.Threading.Internal
         #region IDisposable Members
 
         public void Dispose()
+        {
+            Dispose(true);
+            GC.SuppressFinalize(this);
+        }
+
+        protected virtual void Dispose(bool disposing)
         {
             if (!_isDisposed)
             {
+                _isDisposed = true;
                 Cleanup();
                 _headWaiterEntry.Close();
             }
-            _isDisposed = true;
         }
 
         private void ValidateNotDisposed()
         {
-            if(_isDisposed)
+            if (_isDisposed)
             {
                 throw new ObjectDisposedException(GetType().ToString(), "The SmartThreadPool has been shutdown");
             }