Chcę kolejkować zależne zadania w kilku przepływach, które należy przetworzyć w kolejności (w każdym przepływie). Przepływy mogą być przetwarzane równolegle.Zadania zależne od kolejkowania, które mają być przetwarzane przez pulę wątków
Mówiąc konkretnie, potrzebuję dwóch kolejek i chcę, aby zadania w każdej kolejce były przetwarzane w kolejności. Oto próbka Pseudokod do zilustrowania pożądanego zachowania:
Queue1_WorkItem wi1a=...;
enqueue wi1a;
... time passes ...
Queue1_WorkItem wi1b=...;
enqueue wi1b; // This must be processed after processing of item wi1a is complete
... time passes ...
Queue2_WorkItem wi2a=...;
enqueue wi2a; // This can be processed concurrently with the wi1a/wi1b
... time passes ...
Queue1_WorkItem wi1c=...;
enqueue wi1c; // This must be processed after processing of item wi1b is complete
tutaj jest schemat ze strzałkami ilustrujący zależności między elementów roboczych:
pytanie brzmi, jak mogę to zrobić za pomocą C# 4.0/.NET 4.0? Obecnie mam dwa wątki robocze, po jednym na kolejkę i używam BlockingCollection<>
dla każdej kolejki. Chciałbym zamiast tego wykorzystać pulę wątków .NET i jednocześnie wątki robocze przetwarzać elementy jednocześnie (przez przepływy), ale szeregowo w ramach przepływu. Innymi słowy, chciałbym móc wskazać, że na przykład wi1b zależy od zakończenia wi1a, bez konieczności śledzenia zakończenia i pamiętania wi1a, kiedy nadejdzie wi1b. Innymi słowy, chcę tylko powiedzieć: "Chcę wysłać element pracy dla kolejki1, który ma być przetwarzany seryjnie z innymi elementami, które już przesłałem do kolejki1, ale być może równolegle z elementami roboczymi przesłanymi do innych kolejek".
Mam nadzieję, że ten opis miał sens. Jeśli nie, prosimy o zadawanie pytań w komentarzach. Odpowiednio zaktualizuję to pytanie.
Dzięki za przeczytanie.
Aktualizacja:
Podsumowując „wadliwe” rozwiązania do tej pory, są tu rozwiązania z sekcji odpowiada, że nie mogę używać i powód (y), dlaczego nie można z nich korzystać:
TPL zadania wymagają określenia zadania poprzedzającego dla ContinueWith()
. Nie chcę utrzymywać wiedzy na temat zadań poprzedzających każdą kolejkę podczas przesyłania nowego zadania.
TDF ActionBlocks wyglądał obiecująco, ale wydawałoby się, że przedmioty wysłane do ActionBlock są przetwarzane równolegle. Potrzebuję, aby elementy dla określonej kolejki były przetwarzane seryjnie.
Aktualizacja 2:
RE: ActionBlocks
Wydaje się, że ustawienie opcji MaxDegreeOfParallelism
jednego uniemożliwia równoległe przetwarzanie elementów roboczych złożonych z pojedynczym ActionBlock
. Dlatego wydaje się, że posiadanie numeru ActionBlock
na kolejkę rozwiązuje mój problem z jedyną wadą polegającą na tym, że wymaga to instalacji i wdrożenia biblioteki TDF od firmy Microsoft i miałem nadzieję na czyste rozwiązanie .NET 4.0. Jak dotąd jest to zaakceptowana przez kandydata odpowiedź, chyba że ktoś może znaleźć sposób, aby to zrobić z czystym rozwiązaniem .NET 4.0, które nie ulega degeneracji do wątku roboczego w kolejce (którego już używam).
Czy spojrzałeś na Zadanie/Kontynuacja? –
Mam i zauważyłem, że ContinueWith wymaga znajomości poprzedniego zadania. Nie chciałbym śledzić zadań poprzedzających, o których mowa w pierwotnym pytaniu, częściowo dlatego, że musiałbym to zrobić w kolejce. Zamiast tego chciałbym "podpalić i zapomnieć" od punktu zgłoszenia i radzić sobie z błędami i propagacją błędów w predykatach przetwarzania zadań. Innymi słowy, chcę minimalny stan w momencie przesyłania - element pracy i kolejkę do której powinien zostać przesłany. –