Zaznacz stronę

Jak już pisałem we wcześniejszym poście .NET 4 dał nam możliwość wykorzystania kolekcji Thread-Safe.

Jedną z nich, o której chcę dzisiaj napisać jest BlockingCollection

Kolekcja spełnia kilka zadań. Według mnie najważniejsze to:

  • implementacja wzorca Producer – Consumer – o tym jeszcze na pewno napiszę 🙂
  • jednoczesne dodawanie i usuwanie elementów z wielu wątków jednocześnie
  • generyczna
  • anulowanie operacji przez podanie cancellation token

Wymyślmy sobie bardzo prosty przykład.

Mamy listę stringów, do której co jakiś czas jest dodawany nowy element.
Nasza aplikacja co pewien moment pobiera sobie element z tej listy i coś z nim robi po czym go usuwa. Operacje na liście wykonywane są w różnych miejscach.

Implementacja dodawania elementów do listy może wyglądać tak:

Wątki, które będą odczytywać elementy z listy niech wyglądają tak:

W każdym z wątków przed usunięciem elementu z listy staram się sprawdzić czy rzeczywiście jeszcze coś w kolekcji istnieje:

Wszystko powinno działać 🙂

Odpalam aplikację i po chwili dostaję wyjątek:

kolekcjeTS

Jeden z wątków zanim drugi chciał usunąć dane już to zrobił.
I to jest jeden z wielu problemów używania kolekcji przez wiele wątków. Takich przykładów można wymyślać bardzo dużo 🙂

I tu właśnie z pomocą przychodzi nam kolekcja, o której wspomniałem czyli BlockingCollection 🙂

Dzięki temu, że jest to kolekcja generyczna możemy naszą listę w łatwy sposób zamienić na BlockingCollection 🙂

Obiekt BlockingCollection daje nam kilka fajnych metod, które możemy wykorzystać podczas jego używania:

  • Add(T item) – dodanie nowego elementu do kolekcji
  • CompleteAdding() – mówi kolekcji, że więcej danych już nie może być do niej dodawanych
  • Take() – pobiera element z kolekcji
  • TryAdd(T item) – przed dodaniem elementu do listy sprawdza czy jest taka możliwość
  • TryTake(out T item) – przed pobraniem elementu sprawdza czy może to zrobić

Implementacja dodawania elementów do listy będzie wyglądać w ten sposób:

A nasze wątki, które będą odczytywać dane z listy w następujący sposób:

Po uruchomieniu aplikacji jedyny błąd jaki możemy dostać to: System.OutOfMemoryException spowodowany zapełnieniem pamięci przez ciągłe, testowe dodawanie danych do listy 🙂

W ten oto prosty sposób możemy uchronić się przed błędami w naszych aplikacjach, które korzystają z dobrodziejstwa wielowątkowości.

Kod źródłowy do tego przykładu został umieszczony na GitHub

 

 

Share This
%d bloggers like this: