2009-11-04 11 views
16

Tengo una clase que es cara de construir, en términos de tiempo y memoria. Me gustaría mantener un conjunto de estas cosas y distribuirlas bajo demanda a varios hilos en el mismo proceso.¿Hay un grupo de objetos de propósito general para .NET?

¿Existe un grupo de objetos de propósito general que ya ha sido probado y probado? (No quiero combinar COM +)

Respuesta

5

Sin Cheeso, no hay piscina en general objeto como éste. Pero es una buena idea Creo que esto sería bastante simple de desarrollar. La clave es hacer que funcione bien en un entorno enhebrado.

Creo que este es un problema de diseño interesante. Por ejemplo, si esto necesita escalar en el hardware de clase de servidor, y le dará objetos a hilos individuales a menudo, entonces puede hacer esto:

  1. Mantenga un solo grupo central de objetos.
  2. Mantiene un grupo por subprocesos (un caché) que se completa cuando se llama por primera vez para un subproceso y cuando se vacía.

De esta forma, se evita la contención por subproceso para la mayoría de las solicitudes.

Las diferentes condiciones de funcionamiento lo llevarían a un diseño diferente. Por ejemplo, si las asignaciones de objetos son raras o el número de subprocesos es bajo, entonces podría ser más simple simplemente tener un bloqueo alrededor de una colección. Esto no se escalará bien, pero en este caso, sería necesario.

Si diseña correctamente la clase o la interfaz, puede cambiar la implementación a lo largo del tiempo para manejar situaciones más complejas.

1

¿Por qué no simplemente escribe un singleton que solo sirve como puerta de entrada a la matriz de objetos que se ha creado?

Cuando se distribuye un objeto, elimínelo de la lista disponible, colóquelo en la lista de descatalogados y, luego, cuando se devuelva, inviértalo.

Al usar un singleton para esto tiene una clase estática para todo lo que llame, y si la clase costosa es una clase interna del singleton, nada más puede crear la clase costosa, y puede controlar cuántos objetos crear, facilmente

+0

Bueno, eso funcionaría. un grupo de objetos puede ser bastante simple.Pero luego hay otras sutilezas como, una población de objetos acotada (no menor que x, no mayor que y), objetos nombrados, propiedades de objeto, algo así. Me preguntaba si alguien ya lo había diseñado y considerado estas cosas. – Cheeso

+0

@ Cheeso - es posible que desee agregar eso a su pregunta, ya que cambiará la pregunta un poco. –

21

tirado directamente de MSDN, aquí está un ejemplo de la utilización de uno de los nuevos tipos de colección concurrentes en .NET 4:

El siguiente ejemplo muestra cómo implementar una agrupación de objetos con un System.Collections.Concurrent.ConcurrentBag<T> como su almacén de respaldo.

public class ObjectPool<T> 
{ 
    private ConcurrentBag<T> _objects; 
    private Func<T> _objectGenerator; 

    public ObjectPool(Func<T> objectGenerator) 
    { 
     if (objectGenerator == null) 
      throw new ArgumentNullException("objectGenerator"); 
     _objects = new ConcurrentBag<T>(); 
     _objectGenerator = objectGenerator; 
    } 

    public T GetObject() 
    { 
     T item; 
     if (_objects.TryTake(out item)) 
      return item; 
     return _objectGenerator(); 
    } 

    public void PutObject(T item) 
    { 
     _objects.Add(item); 
    } 
} 
+1

Gracias, vi esta. Depende de .NET 4.0. Lamentablemente, estoy dependiendo de NET 2.0. !!! – Cheeso

+1

Enlace, tal vez: [Cómo: Crear un grupo de objetos mediante un banco simultáneo] (http://msdn.microsoft.com/en-us/library/ff458671%28v=vs.110%29.aspx) –

6

La clase ObjectPool propuesta por 280Z28 se ve bastante bien. También podría considerar crear otra clase que implemente IDisposable y ajuste el valor de retorno de GetObject(). Esto asegurará que los objetos se devuelvan a su grupo y se lea bien:

class ObjectPoolReference<T> : IDisposable 
{ 
    public ObjectPool<T> Pool { get; private set; } 

    public T Instance { get; private set; } 

    public ObjectPoolReference(ObjectPool<T> pool, T instance) 
    { 
     Pool = pool; 
     Instance = instance; 
    } 

    ~ObjectPoolReference() 
    { 
     Dispose(); 
    } 

    #region IDisposable Members 

    private bool _Disposed = false; 

    public void Dispose() 
    { 
     if (!_Disposed) 
     { 
      Pool.PutObject(Instance); 

      _Disposed = true; 
     } 
    } 

    #endregion 
} 

//instance of the pool 
ObjectPool<Foo> Pool; 

//"using" ensures the reference is disposed at the end of the block, releasing the object back to the pool 
using (var Ref = Pool.GetObject()) 
{ 
    Ref.Instance.DoSomething(); 
} 
Cuestiones relacionadas