Entwickler-Ecke

WinForms - lock () Problem


Black Rider - So 15.09.13 03:07
Titel: lock () Problem
Hallo zusammen

Ich bin eigentlich der Meinung die Funktionsweise von LOCK() verstanden zu haben. Aber anscheinend ist das nicht der Fall.

Ich habe eine Form in welcher ein neuer Thread gestartet wird um eine Arbeit auszuführen.
Damit das Form den aktuellen Fortschritt weiss, habe ich eine Variable erstellt wodrauf beide Threads (Arbeiterthread und Formthread) zugreiffen sollten.

Deklaration:

C#-Quelltext
1:
2:
private static Int32 tsm_tries = 0;
private static Object lockvar_tsm_tries = "";

Steht in einer speziellen Klasse dafür. Habe ich auch schon mit ca 25 anderen Variablen auch in dieser Klasse so gemacht, funktionierte immer.

Zudem habe ich, bis jetzt, nur EINE Methode erstellt welche diese 2 Variablen aufruft oder sonst in irgend einer Weise verwendet.

C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
public static void ConnectionTries_AddOne()
{
     lock (lockvar_tsm_tries)
     {
           tsm_tries++;
     }
}


Zudem mache ich vor dem Ausführen eine Haltemarke bei der lock Zeilte und bei der ++ Zeile.
Ich starte mein Programm. Der neue Thread wird gestartet, dieser hält bei der lock an. Wenn ich dann auf weiter drücke, kommt dieser aber nie bei der tsm_tries++; Zeile an. Er kommt auch nicht nochmal bei der lock Zeile an. Also ist er eindeutig bei der lock Zeile hängen geblieben. Wie wenn der Code durch den Lock schon gesperrt wäre, da ich da aber einen Haltepunkt habe, weiss ich das er zu 100% das erste mal darauf zugreifft und somit auch in den Code rein kommen müsste.

Kann mir da jemand helfen? :(

Freundliche Grüsse

Black Rider

Moderiert von user profile iconTh69: C#-Tags hinzugefügt


jaenicke - So 15.09.13 06:16

Hast du das ganze mal unabhängig von deinem ganzen Projekt getestet? Einfach in einem kleinen Testprojekt?
Erstens macht das das ganze einfacher zu debuggen, zweitens siehst du, ob es an dem Quelltext liegt und drittens könntest du das Testprojekt dann hier einfach posten. Denn der von dir gepostete Quelltext sieht eigentlich korrekt aus.


Th69 - So 15.09.13 09:49

Hallo Black Rider,

hast du noch andere lock-Objekte genau so deklariert? Deine zweite Zeile kommt mir komisch vor - nimm besser

C#-Quelltext
1:
private static Object lockvar_tsm_tries = new Object();                    

Bei "" bin ich mir nicht sicher, ob der Compiler die nicht intern so optimiert, daß alle Referenzen dann auf die gleiche Instanz zeigen (und das wäre für den lock dann eben ein Deadlock ;-)).

P.S: Bitte demnächst den Code selber hier im Forum als C# kennzeichnen, danke.


jaenicke - So 15.09.13 10:58

user profile iconTh69 hat folgendes geschrieben Zum zitierten Posting springen:
Bei "" bin ich mir nicht sicher, ob der Compiler die nicht intern so optimiert, daß alle Referenzen dann auf die gleiche Instanz zeigen (und das wäre für den lock dann eben ein Deadlock ;-)).
Darauf bin ich nicht gekommen, aber in Visual C# 2010 passiert das jedenfalls nicht.


jfheins - So 15.09.13 11:51

Die Optimierung wird ziemlich sicher durchgeführt.

Mir erschließt sich nur nicht, warum das dann ein Deadlock sein sollte. Das passiert soch eigentlich nur, wenn in dem lock {} Statement noch auf den anderen Thread wartet, und dieser dann versucht auf den Ursprungsthread zu warten. Da ich hier nirgendwo etwas sehe was mit Warten zu tun hat, sehe ich auch keine Möglichkeit für ein Deadlock.


Th69 - So 15.09.13 12:35

Hallo,

ich meinte, wenn er noch anderen Code hat, der genau so aufgebaut ist und in diesem er evtl. wartet (denn wenn beide dann intern den selben Lock benutzen würden, dann könnte dies ein Deadlock sein - denn so liest sich ja die Beschreibung von user profile iconBlack Rider).
Aber das beste ist wohl, wir warten auf ein Testprojekt (anstatt darüber zu spekulieren).


Black Rider - So 15.09.13 15:13

Hallo zusammen

Vielen Dank für die Antworten.

Auf die lock variable wird ansonsten von nirgend's zugegriffen. Ein Deadlock ist also auszuschliessen.
Ich habe daraufhin ein Testobjekt gemacht. Wie sollte es auch anders sein, da hat es ohne Probleme funktioniert.
Ich habe dann wieder weiter ausprobiert, Thread als Klassenmember deklariert etc. War nix.

Des Rätsels Lösung war die von Th69

C#-Quelltext
1:
private static Object lockvar_tsm_tries = new Object();                    


Ich habe es mehrmals getestet. Wenn ich new Objekt verwende, geht er in den gesicherten Code rein. Wenn ich "" verwende, geht er in den gesicherten Code nicht rein.
Ehrlich gesagt, ich verstehe es nicht. Meine Anwendung umfasst atm 25000 Zeilen. Ich habe wie schon erwähnt in einer anderen Klasse ca. 25 andere Variablen auch so gesichert. Da Software läuft schon seit 8 Monaten täglich in der Firma.

Aber bei diesem Beispiel scheint es wirklich nur mit new Object zu klappen :/

So, Sonntagnachmittag auch verbraten. Wenigstens haben wir den Fehler nun gefunden :)

Nochmal Danke und einen schönen Abend noch.

Gruss

Black Rider


Th69 - Mo 16.09.13 08:58

Hallo Black Rider,

du solltest deshalb auch alle lock Variablen auf "new Object()" umstellen.
Ich verstehe auch nicht, wie ihr bei eurem Projekt auf die Zuweisung "" gekommen seid? Es sollte doch jedem klar sein, daß

C#-Quelltext
1:
2:
string s = "";
string s2 = "";

intern vom Compiler optimiert werden könnte (und nichts anderes ist ja euer bisheriger Code).


Black Rider - Mo 16.09.13 11:35

Da ich mir C# selber beigebracht habe, muss ich diesen Fehler wohl von irgend einem Bsp. aus dem Internet übernommen haben.

Gruss Black Rider