[C#] Drugi wątek korzystający z listy

0

Mam jeden wątek, który obficie i sowicie korzysta z listy (dopisuje dane, kasuje je, przetwarza i robi inne cuda jakie się mojej nauczycielce od informatyki nie śniły). Chodzi o to że wczoraj, 1 kwietna (we prima aprilis) stwierdziłem że budowa aplikacji musi trochę zmienić kształt i projekt musi mieć koniecznie jeszcze jeden wątek spisujący dane z tej listy. Z początku myślałem że to żart ale tak nie było.

I oto dochodzimy do sedna sprawy:
czy przez tenże drugi wątek, który będzie spisywał dane z listy (w jednym tylko miejscu) muszę lockować każde odwołanie do listy w tym pierwszym wątku?

0

Jeżeli spisując dane zależy ci na tym żeby w międzyczasie nie ulegały one zmianom to musisz je lockować w obydwu wątkach. W pierwszym zamek na modyfikacje listy,a w drugim na odczyt.
A tak w ogóle to nie lepiej byłoby wątek roboczy obciążyć operacjami na liście?

0

to już nawet nie chodzi o to żeby nie ulegały modyfikacjom tylko żeby nie sypało wyjątkami
bo teraz wywala różne dziwne wyjątki raz na jakiś czas że niby brakło pamięci (przy modyfikacji z drugiego wątku pierwszy odczytuje jakiś dziwny size i próbuje za-alokować jakąś wielką liczbę pamięci) albo wyjątek że lista się zmieniła w pętli foreach
więc gdzie lock jest potrzebny?

właściwie to jak działa lock?
jak dam

lock(a)
{
a.cos();
}

w jednym wątku to drugi wątek poczeka na zwolnienie "a" przy poleceniu

a.cos();

czy tylko jeżeli też napotka lock?

1

o teraz wywala różne dziwne wyjątki raz na jakiś czas że niby brakło pamięci (

jakie?

więc gdzie lock jest potrzebny?

Tam gdzie jest niebezpieczeństwo że dwa wątki na przykład jednocześnie spróbują zmienić jedną wartość.

właściwie to jak działa lock?

Nikt nie będzie mógł skorzystac z zalochowanego obiektu. Czyli drugi wątek poczeka (dlatego nieumiejętne korzystanie z locka może zamulać aplikację).

0
korzystam_z_życia napisał(a)

w jednym wątku to drugi wątek poczeka na zwolnienie "a" przy poleceniu
a.cos();
czy tylko jeżeli też napotka lock?
oba watki musza sprobowac wykonac LOCK na tym samym obiekcie, czyli tutaj np. lock(a), inaczej lock() ma dużą szansę niezadziałać w ogole, moze poza drobnym spowolnieniem watku.

0
MSM napisał(a)

o teraz wywala różne dziwne wyjątki raz na jakiś czas że niby brakło pamięci (

jakie?

emmm... OutOfMemoryException :|

dobra, dzięki - będę musiał to jeszcze przemyśleć bo teraz dawanie locka w tylu miejscach wydaje mi się głupie

0

Foreach w ogóle nie jest thread-safe, więc tu obowiązkowo lock.

0

nie wiem jak duza jest twoja kolekcja, ale jesli bardzo duza (na co moze wskazywac problem z pamiecia), to nie uzywaj foreach, tylko for lub List.ForEach - sa o wiele wydajniejsze, znajdziesz w necie kilka porownan wydajnosci i wytlumaczenie czemu

gdzie leci ten OutOfMemoryException? jakie typy obiektow masz w tej liscie? i co robisz w watku czytajacym z tymi danymi? jak je wyswietlasz?

0

lista ma zawsze około 10 elementów własnego typu dziedziczącego po Panel
mimo to używam List.ForEach, ale generuje to takie same problemy jak zwykłe foreach więc nie chciałem komplikować
OutOfMemory leci przy próbie przepisania listy (ale to się zdarza bardzo rzadko). Przy debugowaniu odkryłem że prawdopodobnie dzieje się to gdy inny wątek próbuje dodać nowy element do tej listy - wtedy w jednej konkretnej mikrosekundzie przy odwołaniu do Size listy (o który pyta metoda przepisująca) zwraca bardzo dużą wartość rzędu kilku miliardów mimo że liczba elementów zwiększa się tylko z przykładowo z 10 do 11, przez to program próbuje na nową listę zaalokować gigantyczną liczbę pamięci i leci wyjątek
danych generalnie nie wyświetlam, wątek czytający zapisuje je do loga

0

sorry, dziedziczy tylko po IFormattable - pomyliłem projekty
ale to chyba generalnie nie robi przy tym problemie różnicy

w każdym razie teraz zajmuję się innym projektem, a tamten jest do przebudowania
także problem jest już tak w połowie nieaktualny

0
autor_wątku napisał(a)

zwraca bardzo dużą wartość rzędu kilku miliardów mimo że liczba elementów zwiększa się tylko z przykładowo z 10 do 11, przez to program próbuje na nową listę zaalokować gigantyczną liczbę pamięci i leci wyjątek

jak dla mnie, to najlepszy dowód, ze Twoje petle/algorytmy/etc nie sa bezpieczne pod katem wielowatkowosci.. ot, jeden watek wlasnie kontruowal/przealokowywal sobie wewnetrzne bufory listy, gdy nagle zostal wywlaszczony i do glosu doszedl drugi watek ktory mial zamiar te liste sobie przeiterowac/skopiowac/etc..

Twoje rozwiazanie najprawdopodobniej brzmi:
watek A: {blahblah modyfikujliste blahblahblah } ->{blahblah lock(lista) {modyfikujliste} blahblahblah }
watek B: {blahblah kopiujliste blahblahblah } ->{blahblah lock(lista) {kopiujliste} blahblahblah }

lub jakies sprytne użycie volatile oraz swap, ale na Twoim miejscu nie probowalbym

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