operacje wielowątkowe na typach generycznych

0

Witam, mam taki mały problem w c# / WPF

Otóż mam aplikacje 3 wątkową (+ wątek główny) i praca każdego z tych wątków polega na przeglądaniu elementów listy i operacje na nich, oczywiście w pętli foreach. Problem polega na tym, że w czasie kiedy jeden wątek jest w trakcie przeglądania listy, a drugi wtedy doda lub usunie element z listy to na pierwszym wyskakuje exception błąd podczas wyliczania, no i jak sobie z tym poradzić?
Ja wymyśliłem 3 sposoby, nie wiem czy są coś warte, dlatego chciałbym spytać mądrzejszych i bardziej doświadczonych ode mnie jak ominąć ten problem. A te moje pomysły to:

  1. zmienić foreach na for, wtedy przy przejściu do następnego elementu liczenie będzie odbywało się na nowo, błąd nie wystąpi, ale przy dużej liczbie elementów listy pewnie będą spore straty na wydajności
  2. wrzucić operacje na listach do sekcji krytycznej, rozwiązanie oczywiste, no ale najmniej mi sie podoba bo co to za program wielowątkowy kiedy pracować na raz może tylko jeden wątek (praca każdego wątku to tylko i wyłącznie operacja na liście)
  3. przed pętlą foreach przepisać całą liste na nową i to na niej operować, tylko czy to nie będzie zajmować za dużo czasu?
1

A czy kolejność elementów ma znaczenie? Możesz użyć ConcurrentBag

EDIT:
Dlaczego kilka wątków przegląda listę? Sprawdza czy coś się zmieniło czy inna przyczyna?

0

duża ta lista?

0
  1. kolejność nie ma znaczenia
  2. lista do 1000 obiektów max
0

Jakie dokładnie operacje na liście wykonujesz, że zamiana foreach na for ma spowodować straty wydajności? Bo mi to brzmi jak jakieś czary.

1

jedyne co wg mnie ma sens to

  1. wątek przeglądający pracuje na kopii
  2. wątki dodające/usuwające przez sekcji krytyczne czy inne rozwiązanie
0

no z tego co wiem to kiedy na liście operuje pętla for to kiedy chce ona się dostać do np. elementu nr 4 to liczy od 0 do 4, potem chce się dostać do elementu nr 5 i znowu liczy od 0 do 5, zamiast pobrać adres elementu nr 5 z elementu nr 4 jak to robi petla foreach

tak mi tłumaczył znajomy x czasu temu kiedy zaczynałem się bawić w programiste, jeśli to nieprawda to mnie poprawcie

0

Pętla niczego nie liczy, dostęp do elementów w liście odbywa się po indeksie. A foreach to nie pętla tylko cukier składniowy na iteratory, faktycznie wielkość kolekcji nie ma znaczenia w tym przypadku, bo zwracany jest następny element dopóki istnieje. Różnica jest taka, że jedna iteracja foreach to wywołanie dwóch metod, a for to wywołanie jednej, więc foreach w każdym przypadku jest pomijalnie wolniejszy od for.

0

hmm to wychodzi na to, że rzeczywiście to co pisałem było czarami :p
dzięki za wyprowadzenie z błędu :)

wracając do tematu
chyba użytkownik Sarrus udzielił najciekawszej odpowiedzi, zamiana zwykłej listy na ConcurrentBag chyba będzie najlepsza, z tego co czytam to ten typ to lista z zaimplementowanym wsparciem dla wielu wątków a tego mi właśnie potrzeba

ps: wiele wątków operuje na jednej liście ponieważ obiekty tej listy to obiekty klas a każdy taki obiekt to jeden połączony klient przez socket tcp, pierwszy wątek nasłuchuje nowe wiadomości, zapisuje je i wysyła potwierdzenie odbioru, drugi wykonuje zlecone zadania na liście, trzeci co 10 sekund sprawdza połączenie (czy nie nastąpiło zerwanie)

1 użytkowników online, w tym zalogowanych: 0, gości: 1