Witam.
W jaki sposób C# synchronizuje wątki? Czy w przypadku wywołania metody poprzez delegat tworzony jest osobny wątek? Jeśli tak to w jaki sposób synchronizować zapis/odczyt danych w wątku tworzonym przez obsługę wywołania delegata, oraz wątkiem tworzonym jawnie przez programistę? Próbowałem synchronizować poprzez użycie słowa kluczowego lock, ale w wątku przez mnie utworzonym występuje błąd.
Kod w uproszczeniu wygląda następująco:
- Tworzone są 4 wątki ( w uproszczeniu)
- Wątek pierwszy subskrybuje zdarzenia wątku 2 i vice versa, 2-3, 3-4.
- Poniższy kod wykonuje każdy z wątków, metoda NeighborDiscoverySend oraz NeighborTableSolicitation wywołuje zdarzenia, które są odbierane i wykonywane przez subskrybentów.
public void process()
{
while(this.thread_processing == true)
{
NeighborDiscoverySend();
//Tu błąd: "Collection was modified after the enumerator was instantiated."
//Rozumiem że iteruje po kolekcji do której został dodany/usunięty element w trakcie iterowania po kolekcji.
//Dlaczego skoro w obsłudze zdarzenia zablokowaliśmy dostęp do kolekcji (lock(sync))
foreach (NeighborTable n in myNeighborTable)
{
if (n.NeighborID != this.myID)
{
NeighborTableSolicitation(n.NeighborTimeStampTicks);
}
}
Thread.Sleep(5000);
}
}
}
- Obsługa zdarzenia wygląda następująco:
private void NeighborDiscoveryReceive(NetworkMessage msg)
{
lock (sync)
{
if (myNeighborTable.Count == 0)
{
this.howManyNodesIntNetwork++;
this.myNeighborTable.AddFirst(new NeighborTable(this.myTimeStampTicks, this.myName, this.myID, "Me"));
this.howManyNodesIntNetwork++;
this.myNeighborTable.AddLast(new NeighborTable(msg.senderTimeStampTicks, msg.senderName, msg.senderID, "Short"));
}
else
{
if (NeighborTable.Exist(this.myNeighborTable, msg.senderName) == false)
{
this.howManyNodesIntNetwork++;
this.myNeighborTable.AddLast(new NeighborTable(msg.senderTimeStampTicks, msg.senderName, msg.senderID, "Short"));
}
}
if (this.myNeighborTable.Count != 0)
{
{
myNeighborTable = NeighborTableSort(this.myNeighborTable);
myNeighborTable = UpdateID(this.myNeighborTable);
this.UpdateMyID(this.myNeighborTable);
}
}
}
}
-
Dodam, że powyższy błąd występuje z częstotliwością 1/3, czasem działa, czasem nie ;]
-
Całość kodu: http://www.speedyshare.com/files/30816329/TestSynchro.rar