Wątki - synchronizacja kolekcji

0

Witam wszystkich

Jestem początkującym w dziedzinie wielowątkowości i mam nurtujący mnie od dłuższego czasu problem, z którym bez Waszej pomocy nie będę sobie w stanie poradzić, a mianowicie próbuję zsynchronizować listę, tak, aby kilka wątków mogło z niej na raz korzystać (dodawanie, usuwanie i pobieranie danych z elementów w niej zawartych).

Operacje na liście wykonuję za pomocą poniższych metod

private void AddToList(List<Zadanie> lista, Zadanie zadanie)
        {
            ICollection coll = lista;
            lock (coll.SyncRoot)
            {
                lista.Add(zadanie);
            }
        }

        private void RemoveFirstEl(List<Zadanie> lista)
        {
            ICollection coll = lista;
            lock (coll.SyncRoot)
            {
                lista.RemoveAt(0);
            }
        }

        private int GetPowerFromList(List<Zadanie> lista)
        {
            int output = 0;
            ICollection coll = lista;
            lock (coll.SyncRoot)
            {
                output = lista[0].PowerNeeded;
            }
            return output;
        }

Nie wiem czemu, ale w pewnych momentach, gdy wiele wątków korzysta z danej listy ona po prostu się zawiesza i nie da się na niej dokonywać żadnych operacji, a wykrycie błędu jest strasznie trudne i nie potrafię sobie sam poradzić. Już dwa dni to rozkminiam ...

Może ktoś wprawnym okiem programisty od razu zlokalizuje problem.
Będę wdzięczny za każdą pomoc!

0

Dzięki, za chęci, ale niestety temat, który przesłałeś/aś nie dotyczy synchronizacji kolekcji.

0

A samo lock(lista) nie wystarczy?

0

a próbowałeś synchronizować obiektem innym niż samą listą?
przykładowo w klasie zrob gdzieś private readonly object locker = new object() i nim synchronizuj.

0

Próbowałem - właśnie taka była moja pierwsza wersja. Z takim "lockerem" efekt działania jest dokładnie taki sam jak z synchronizacją listy.

Kiedy mam kilka wątków i kilka list, które podaje w parametrze powyższych funkcji listy po kolei się zacinają aż do momentu, kiedy działa tylko jedna i tylko na niej poprawnie wykonywane są operacje.

Wydaje mi się, że powinienem stworzyć osobne modyfikujące dla każdej listy z osobna, tylko jeżeli coś się zmieni w jednej funkcji to będę musiał modyfikować je wszystkie.

0

ja bym pomyślał nad opakowaniem listy w jakąś klasę i udostępniać metody z synchronizacja (locker jako prywatne pole w klasie)

0

Ah, sorki, zły link wkleiłem :>
http://msdn.microsoft.com/en-us/library/bb356596.aspx
Ten powinien być dobry

0

A tak zauważyłem że dajes zlock'a na coll a używasz lista, nie powinienneś użytkować coll w tmy przypadku? ( szukam projekciku gdzie miałem takie coś, ale z tego co pamiętam to lock wystarczał )

0

Dziwny problem masz :>
Znalazłem projekcik i miałem tam w sumie takeigo samego locka jak Ty masz, śmigało. Napisałem na szybko brutala co mnoży wątki i gmera w liście, i za nic nie mogę uzyskać efektu "zacinającej się listy" :>
Pokaż więcej kodu bo w tym chyba błędu po prostu nie ma, napisz też w jakiej wersji .NETa skrobiesz, mogą być pewne różnice między wersjamiw pewnych detalach ( if(version<4){dotNEt.Update();} :> )

0

Sądziłem, że to w synchronizacji listy jest błąd, trudno mi było go namierzyć, a potwierdzeniem na jej zacinanie się była obserwacja dynamicznie odświerzającego się listBoxa. Teraz, skoro dzięki waszej pomocy wypróbowałem już każdą metodę z listą podejrzenie pada na mechanizm, którym odświeżam listBoxa:

delegate void RefreshListServer3Callback();
        private void RefreshListServer3()
        {
            if (this.lbServer3.InvokeRequired) //lbServer3 to nazwa listBoxa, którego odświerzam
            {
                RefreshListServer3Callback d = new RefreshListServer3Callback(RefreshListServer3);
                this.Invoke(d);
            }
            else
            {
                ((CurrencyManager)lbServer3.BindingContext[lbServer3.DataSource]).Refresh();
            }
        }

Nie jestem pewien, czy ten skrypt nie jest przyczyną :/
(korzystam z VS 2010)

0

((CurrencyManager)lbServer3.BindingContext[lbServer3.DataSource]).Refresh();
to tez zrob w lock na liscie, ktora jest zrodlem dla lbServer3

0

O wybacz, ale nie zauważyłem, że dopisałeś ten post. Od razu sprawdziłem, czy to coś pomogło, ale niestety nie, program zachowuje się dokładnie tak samo.

Pozbyłem się tego problemu, poprzez zmniejszenie ilości odświerzania listBoxa.

Listy natomiast synchronizują się bezbłędnie.

Dzięki wszystkim za pomoc!!

0
LukTar napisał(a)

Pozbyłem się tego problemu, poprzez zmniejszenie ilości odświerzania listBoxa.

yyyyy? tzn. co wczesniej robiles? jesli jakims timerem masakrowales aplikacje co kilka, kilkanascie milisekund, to nie dziw sie ze dostawala tyle komunikatow, ze nie dawala sobie rady z ich obsluga i miala ochote zrobic sobie fajrant :)

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