Wpis z mikrobloga

Mam problem z aplikacją wielowątkową i potrzebuje porady.
Mam apke w WPF'ie, która odbiera dane przez SerialPort od trzech czujników (otrzymuje ramki od każdego z czujników na ten sam serialPort a czujnik poznaje po nagłówku ramki). Każdy z czujników wysyła swoją ramkę z częstotliwością jakieś 50 Hz (czyli plus minus otrzymuje ramki z częstotliwością 150 Hz uwzględniając wszystkie). W aplikacji mam m.in 3 obiekty tej samej klasy które reprezentują każdy z czujników. Jeżeli odbiorę ramkę to dane z ramki przekazuje do funkcji (która wykonuje pewne obliczenia) w odpowiednim obiekcie (na podstawie nagłówka ramki). Oprócz tego wszystkiego z częstotlwiością ok 25 Hz będzie chodziła symulacja 3D bazujaca na danych z czujników po przeliczeniu.
Zrobiłem to następująco:
- odpalam wątek który w kółko odbiera dane z serialPort'u.
- gdy odbiorę ramkę to odpalam kolejny wątek w którym wykonuje się funkcja obliczająca dla danego czujnika/obiektu.
(czyli gdy mam 3 czujniki może być tak że 3 'poboczne' wątki zostaną odpalone jeden po drugim dla każdego z czujników. Wątek dla konkretnego czujnika powinien się skończyć przed pojawieniem się kolejnej ramki dla tego czujnika. czyli funkcja obliczająca powinna wyrobić się co 50Hz).
- odpalam timer w którym z częstotliwościową co około 25 Hz następuje update symulacji 3D.

Problem jest w tym że te wszsytkie wąki dodatkowe oprócz oczywiście timera (czyli odbieranie danych z seriala i wątki liczące odplałem przez delegaty i beginInvoke). O ile odpalanie delegaty w przypadku seriala chyba nie jest problemem bo wątek utworzony zostaje raz i cały czas się wykonujem to odpalanie 50 razy na sekunde wątków liczących dla każdego z czujników nie jest najlepszym rozwiązaniem
Pytanie co powinienem użyć do tworzenia nowych wątków: thread, threadPool czy coś innego?

ps dodam że funckje obliczające są dość wymagające i powinny zostać potraktowane priorytetowo.
#pytanie #csharp #wpf #programowanie
  • 4
@PanCogito Witam, ja problem rozwiązałbym modelem producent/konsument, odpaliłbym osobne wątki liczące które w nieskończonej pętli pobierały by dane z kolejki. Dane do nich można przekazywać przez kolejkę ConcurrentQueue posiada blokady do bezpiecznego dodawania/usuwania. Nie wiem ile masz danych do przekazywania i przeliczania ale myślę że w ten sposób dałoby radę.
@wcaleNieTakiDobry: czyli w takim wypadku po prostu odpalam 3 wątki nieskończone dla każdego z czujnika osobno. Ale w takim wypadku będę niepotrzebnie? zajmował czas w tych wątkach gdy nie będzie danych, czy nie powinienem jakoś zawieszać te wątki gdy nie ma nowych danych?
@PanCogito: jeżeli potrzebujesz obliczać coś równolegle nie koniecznie to musi być osobny wątek dla każdego z czujników, najlepiej wykorzystać wielowątkową architekturę współczesnych procesorów tj. utworzyć wątki w liczbie zbliżonej do ilości wątków procesora, daje to możliwie najlepsze wykorzystanie procesora (przy dużym obciążeniu). Jest to świetnie opisane w książce "Programowanie równoległe i asynchroniczne w C# 5.0". Wiem że mogę zaburzać Ci koncepcję rozwiązania ale ramki które odbierasz możesz wrzucać bezpośrednio w kolejkę
@wcaleNieTakiDobry: po drobnym namyśle stwierdziłem że faktycznie nie potrzebuje 3 wątków dla każdego z czujników. Wystarczy jeden wątek który będzie na bieżąco obliczał to co będzie wrzucane w kolejkę. Obliczenia nie muszą być wykonywane ściśle równolegle warunek jest tylko żeby obliczenia dla danego czujnika wyrobiły się przed pojawieniem się kolejnych danych dla tego czujnika. Czyli przykładowo gdy dostanę 3 ramki z 3 różnych czujników bezpośrednio jedna za drugą to oczywiście zgodnie