Reusable
|
Note: This API is now obsolete.
[ObsoleteAttribute("It is not recommended to use this class because the need for pooling is rare and implementations of pooling can be dangerous.")] public class ReusableObjectPool<T> where T : class, new()
The ReusableObjectPoolT type exposes the following members.
Name | Description | |
---|---|---|
ReusableObjectPoolT | Initializes a new instance of the ReusableObjectPoolT class |
Name | Description | |
---|---|---|
Clear | Releases all the objects currently cached in the pool. | |
Equals | Determines whether the specified object is equal to the current object. (Inherited from Object) | |
Finalize | Allows an object to try to free resources and perform other cleanup operations before it is reclaimed by garbage collection. (Inherited from Object) | |
GetHashCode | Serves as the default hash function. (Inherited from Object) | |
GetPoolSize | Gets the number of items currently contained in the pool. | |
GetType | Gets the Type of the current instance. (Inherited from Object) | |
MemberwiseClone | Creates a shallow copy of the current Object. (Inherited from Object) | |
ReturnObject | Returns object to the pool. | |
SetPoolSize | Allocates the pool to the desired size. | |
TakeObject | Gets an object from the pool, or creates a new one if no pool items are available. | |
ToString | Returns a string that represents the current object. (Inherited from Object) |
Name | Description | |
---|---|---|
GetEnumValueOrDefault |
Gets the enumeration constant for value, if defined in the enumeration, or a default value.
(Defined by EnumExtensions) | |
GetEnumValueOrDefaultT |
Gets the enumeration constant for this value, if defined in the enumeration, or a default value.
(Defined by EnumExtensions) |
Object pooling can offer a significant performance boost in some scenarios. It is most effective when the cost of construction is high and/or the rate of instantiation is high.
This object pool is statically created at application startup, one per type, and is available for all components and classes within an application domain. Every time you need to use an object, you take one from the pool, use it, then return it to the pool when done. This process can be much faster than creating a new object every time you need to use one.
When objects implement ISupportLifecycle, the ReusableObjectPoolT will automatically attach to the Disposed event and return the object to the pool when it's disposed. When an object is taken from the pool, the Initialize method will be called to reinstantiate any need member variables. If class tracks a disposed flag, it should be reset during call to the Initialize method so that class will be "un-disposed". Also, typical dispose implementations call SuppressFinalize(Object) in the Dispose method, as such the ReRegisterForFinalize(Object) should be called during Initialize method to make sure class will be disposed by finalizer in case Dispose method is never called.
/// <summary> /// Class that shows example implementation of reusable <see cref="ISupportLifecycle"/>. /// </summary> public class ReusableClass : ISupportLifecycle { #region [ Members ] // Events /// <summary> /// Occurs when the <see cref="ReusableClass"/> is disposed. /// </summary> public event EventHandler Disposed; // Fields private System.Timers.Timer m_timer; // Example member variable that needs initialization and disposal private bool m_enabled; private bool m_disposed; #endregion #region [ Constructors ] /// <summary> /// Releases the unmanaged resources before the <see cref="ReusableClass"/> object is reclaimed by <see cref="GC"/>. /// </summary> ~ReusableClass() { Dispose(false); } #endregion #region [ Properties ] /// <summary> /// Gets or sets a boolean value that indicates whether the <see cref="ReusableClass"/> object is currently enabled. /// </summary> public bool Enabled { get { return m_enabled; } set { m_enabled = value; if (m_timer != null) m_timer.Enabled = m_enabled; } } #endregion #region [ Methods ] /// <summary> /// Initializes the <see cref="ReusableClass"/> object. /// </summary> public void Initialize() { // Undispose class instance if it is being reused if (m_disposed) { m_disposed = false; GC.ReRegisterForFinalize(this); } m_enabled = true; // Initialize member variables if (m_timer == null) { m_timer = new System.Timers.Timer(2000.0D); m_timer.Elapsed += m_timer_Elapsed; m_timer.Enabled = m_enabled; } } /// <summary> /// Releases all the resources used by the <see cref="ReusableClass"/> object. /// </summary> public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } /// <summary> /// Releases the unmanaged resources used by the <see cref="ReusableClass"/> object and optionally releases the managed resources. /// </summary> /// <param name="disposing">true to release both managed and unmanaged resources; false to release only unmanaged resources.</param> protected virtual void Dispose(bool disposing) { if (!m_disposed) { try { if (disposing) { // Dispose member variables if (m_timer != null) { m_timer.Elapsed -= m_timer_Elapsed; m_timer.Dispose(); } m_timer = null; m_enabled = false; } } finally { m_disposed = true; if (Disposed != null) Disposed(this, EventArgs.Empty); } } } // Handle timer event private void m_timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e) { // Do work here... } #endregion }
If the pool objects do not implement ISupportLifecycle you can still use the object pool, but it will be very imporant to return the object to the pool when you are finished using it. If you are using an object scoped within a method, make sure to use a try/finally so that you can take the object within the try and return the object within the finally. If you are using an object as a member scoped class field, make sure you use the standard dispose pattern and return the object during the Dispose method call. In this mode you will also need to manually initialze your object after you get it from the pool to reset its state.