2012-03-25 21 views
12

Potrzebuję środowiska, które musi utrzymywać różne kolejki zadań, i dla każdego z nich mieć dobrze określoną liczbę współbieżnych wątków, które mogą być wykonywane dla każdej kolejki. Coś takiego:C# zadanie zadłużanie wielu kolejek

  • Kolejka 1 -> 3 wątki;
  • Kolejka 2 -> 6 wątków;

Rodzaj systemu zadań. Udało mi się samemu to zaimplementować używając zwykłego starego kodu C# (alias System.Threading.Thread, lock and queue), który działa więcej niż dobrze przez 1 rok. Jednak wciąż czytam artykuły o cudach TaskFactory i TaskScheduler, o możliwościach tego z wbudowanymi klasami w .NET, ale nie udało mi się znaleźć przykładu, aby to udowodnić. Chciałbym przetestować to i porównać z tym, co mam teraz, aby sprawdzić, czy działa lepiej, a jeśli tak, to je zastąpić.

Więcej, mogę żyć bez konieczności ograniczania/ustawiania liczby równoległych wątków dla każdej kolejki, o ile mogę uzyskać guarantee, że jeśli element kierowany do kolejki nr 2 jest wykonywany bez problemu, nawet jeśli kolejka nr 1 jest wykonywana przy pełnym obciążeniu.

Moje pytanie brzmi - czy jest coś w .net 4 i więcej, czy ktoś może wskazać mi przykład? Szukam jednego przez cały tydzień i nie udało mi się uzyskać czegoś istotnego.

Odpowiedz

3

Możesz spróbować utworzyć odpowiednik LimitedConcurrencyLevelTaskScheduler wymieniony w this example lub zajrzeć do harmonogramu priorytetów wspomnianego here.

+0

Aby osiągnąć to, co OP wydaje się chcieć, nie wystarczy, że zadania są wydawane w kolejce priorytetowej.Wątki wykonujące zadania w kolejce nr 2 muszą działać z wyższym priorytetem niż te obsługujące kolejkę nr 1. Nie jest jasne, czy takie rozwiązania pozwalają na to? –

+1

Tak, prawdopodobnie to jest to, co pasuje do tego, czego potrzebuję. Implementuje różne kolejki i ogranicza maksymalną liczbę elementów, które mogą być wykonywane w tym samym czasie i nie zatrzymuje drugiej kolejki, aby uruchamiać inne elementy równolegle z pierwszą kolejką. Dzięki! – dcg

6

To jest naprawdę całkiem banalne przy użyciu TPL i nowe kolekcje w System.Collections.Concurrent.

Dla Państwa potrzeb polecam BlockingCollection<T>. Domyślnie używa ConcurrentQueue<T> jako podstawowego sklepu, który jest idealny do tego, co chcesz.

var queue = new BlockingCollection<Message>(); 

Aby ustawić jakiś działający kod na tych wiadomościach i kontrolować, ile może wykonywać równolegle jest tak proste, jak to:

//Set max parallel Tasks 
var options = new ParallelOptions 
{ 
    MaxDegreeOfParallelism = 10 
}; 

Parallel.ForEach(queue.GetConsumingEnumerable(), options, msg => 
{ 
    //Do some stuff with this message 
}); 

Więc co tu się dzieje? No cóż ...

Połączenie z numerem GetConsumingEnumerable() zablokuje się, dopóki nie zostanie zużyte coś w rozmiarze queue. Jest to świetne, ponieważ nie jest potrzebny dodatkowy kod do sygnalizowania, że ​​nowa praca jest gotowa do zrobienia. Zamiast tego, jako wypełnienie queue, nowe zadanie z Twoim (anonimowym) delegatem zostanie wyrzucone z elementem.

Obiekt ParallelOptions pozwala kontrolować działanie Parallel.ForEach. W tym przypadku mówisz, że nigdy nie chcesz więcej niż 10 zadań wykonywanych w tym samym czasie. Należy pamiętać, że Zadania! = Wątki. Szczegóły są mętne, ale nie trzeba dodawać, że wiele się dzieje pod maską. To wszystko można wymyślić, ale nie dla osób o słabym sercu.

Istnieje oczywiście wiele szczegółów, których tu nie omówiłem, ale mam nadzieję, że można zobaczyć, jak prosta i ekspresyjna może być biblioteka zadań.

+0

OP wydaje się potrzebować priorytetowej kolejki i wątków priorytetowych, aby najpierw wykonać elementy w kolejce nr 2. –

+2

To nie jest takie wrażenie, jakie mam. Po prostu wskazywał, że musi mieć możliwość kontrolowania liczby równoczesnych zadań, aby nikt w kolejce nie zjadł wszystkich zasobów. Powyższe rozwiązanie można z łatwością rozszerzyć o wiele Kolejki. Wypełnianie tych kolejek zależy od niego, ale dość łatwo kontrolować, ile zadań można wykonać równolegle w ten sposób. Jedna z 50, druga z 10 itd. ... – Josh