2009-11-04 9 views
16

Mam klasę, która jest kosztowna w budowie, pod względem czasu i pamięci. Chciałbym utrzymać pulę tych rzeczy i rozdzielać je na żądanie na wiele wątków w tym samym procesie.Czy istnieje pula obiektów ogólnego przeznaczenia dla .NET?

Czy istnieje puli obiektów ogólnego przeznaczenia, która jest już przetestowana i sprawdzona? (Nie chcę buforowania COM +).

Odpowiedz

5

Nie Cheeso, nie istnieje ogólna pula obiektów jak ten. Ale to dobry pomysł. Myślę, że byłoby to dość proste do opracowania. Kluczową sprawą jest sprawienie, by działało dobrze w środowisku z gwintem.

Myślę, że jest to interesujący problem projektowy. Na przykład, jeśli konieczne jest skalowanie na sprzęcie klasy Sever, a ty możesz często udostępniać obiekty poszczególnym wątkom, możesz to zrobić:

  1. Zachowaj pojedynczą centralną pulę obiektów.
  2. Zachowaj pulę wątków (pamięć podręczną), która jest zapełniana, gdy jest wywoływana po raz pierwszy dla wątku, a gdy staje się pusta.

W ten sposób unikasz rywalizacji między wątkami dla większości żądań.

Różne warunki operacyjne doprowadziłyby do innego projektu. Na przykład, jeśli alokacje obiektów są rzadkie lub liczba wątków jest mała, może być prostsze po prostu zablokowanie kolekcji. To nie będzie dobrze skalowane, ale w tym przypadku będzie musiało.

Jeśli projektujesz klasę lub interfejs poprawnie, możesz z czasem zmienić implementację, aby obsługiwać bardziej złożone scenariusze.

1

Dlaczego nie wystarczy napisać singleton, który służy tylko jako brama do tablicy obiektów, które zostały utworzone.

Po rozdaniu obiektu, usuń go z dostępnej listy, umieść na liście wyewidencjonowanej, a następnie po zwróceniu odwróć.

Używając singletonu, masz klasę statyczną, do której możesz zadzwonić, a jeśli kosztowna klasa jest klasą wewnętrzną singletonu, to nic innego nie może stworzyć kosztownej klasy, a Ty możesz kontrolować, ile obiektów chcesz tworzyć, łatwo.

+0

Cóż, to zadziała. Pula obiektów może być całkiem prosta.Ale są też dodatkowe nicetie, takie jak ograniczona populacja obiektu (nie mniej niż x, nie wyższa niż y), nazwane obiekty, właściwości obiektu, coś w tym stylu. Zastanawiałem się tylko, czy ktoś już to zaprojektował i rozważył te rzeczy. – Cheeso

+0

@Cheeso - możesz dodać to do swojego pytania, ponieważ zmieni ono trochę pytanie. –

21

szarpana prosto z MSDN, oto przykład przy użyciu jednego z nowych typów zbiórki współbieżnych w .NET 4:

Poniższy przykład pokazuje jak zaimplementować basen obiekt o System.Collections.Concurrent.ConcurrentBag<T> jako swojego sklepu podkładowej.

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

Dziękuję, widziałem to. To zależy od .NET 4.0. Niestety zależy mi na NET 2.0. !!! – Cheeso

+1

Link, być może: [Jak: Tworzenie puli obiektów za pomocą ConcurrentBag] (http://msdn.microsoft.com/en-us/library/ff458671%28v=vs.110%29.aspx) –

6

Klasa ObjectPool zaproponowana przez 280Z28 wygląda całkiem nieźle. Możesz także rozważyć utworzenie innej klasy, która implementuje IDisposable i zawija wartość zwracaną przez GetObject(). Dzięki temu obiekty zostaną zwrócone do puli i będą ładnie czytać:

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(); 
} 
Powiązane problemy