2009-03-13 7 views
1

Ich habe ein bisschen Code, den ich nicht richtig herausfinden kann. Das Problem ist, dass das Programm multithreaded ist und innerhalb ein Stück Code, das ich schrieb so diese synchronisiert werden soll:C# Multithreading-Problem mit Monitor-Klasse - möglicher Lifelock?

lock (lockObject) 
{ 
    if (!Monitor.TryEnter(lockObject)) 
    Monitor.Wait(lockObject); 

    //do stuff... 
    Monitor.PulseAll(lockObject); 
} 
Monitor.Exit(lockObject); 

das Problem, das ich habe, ist, dass in einem gewissen Punkt in der Zeit alle Threads zu sein scheinen Schlafen - kann jemand sagen warum? Das Programm läuft endlos weiter und verbraucht fast keine CPU, aber es wird keine Arbeit erledigt - beim Nachverfolgen des Programms habe ich herausgefunden, dass zu irgendeinem Zeitpunkt kein Thread aktiv ist, aber eine ganze Menge von ihnen schläft. Ich kenne den Fehler meistens (; im Falle eines Entwicklers - immer) sitzt 0,5m vor dem Monitor - aber ich kann es mir selbst nicht vorstellen ... vielleicht in ein paar Minuten;)

kann mir bitte jemand das erklären ich - danke im voraus.

+0

Ist das LockObject, das Sie sperren, dasselbe, das Sie einen Monitor.TryEnter ausführen, oder sperren Sie den Typ LockObject? –

+0

ja - das war ein klassischer Tippfehler – Gambrinus

Antwort

1

Gibt es einen Unterschied zwischen LockObject und lockObject? Es ist nicht klar ...

Allerdings! Wenn sie verschiedene Objekte sind, dann zuerst: Sie können nicht Wait auf eine Sperre, die Sie nicht haben ... und TryEnter wird nur false zurückgeben, wenn Sie eine Zeitüberschreitung angeben. Was genau versucht dieser Code zu tun?

Ohne mehr Kontext, ist es nicht ganz klar, was die PulseAll und Wait sind entworfen, um zu tun; beispielsweise here werden sie verwendet, um die Warteschlange zu blockieren, wenn sie zu voll ist (Wait), oder sie freizugeben, wenn Speicherplatz verfügbar wird (PulseAll) usw. Es ist schwierig, Threading-Code ohne die vollständigen Interaktionen zwischen Threads zu debuggen.

Es klingt wie Sie vielleicht gerade brauchen:

lock (lockObject) 
{ 
    // do stuff 
} 

Es gibt zwei unmittelbare Probleme, die ich sehen kann; Erstens ist es nicht offensichtlich, dass Sie die Sperren, die Sie verwenden, immer freigeben (d. h. Ausnahmen). Versuchen Sie einfach, lock für die Enter/Exit zu verwenden - es wird es richtig machen.

Sekunde; wenn alle Threads Wait aufrufen ... wer wird sie aufwecken? Was warten sie für? Wie dargestellt: Ja, sie werden alle unbegrenzt schlafen.

3

Ich assimme die erste Lock-Anweisung ist ein Tippfehler und du meintest lock (lockObject) (Kleinbuchstaben).

Ich denke, dass Sie hier ein bisschen falsch verstehen Sperren. Der if-Block in deinem Code wird niemals wahr sein. Der Grund dafür ist, dass Schloss (LockObject) exapands tatsächlich auf die folgende

Monitor.Enter(lockObject); 
try { 
... 
} finally{ 
Monitor.Exit(lockObject); 

Also von der Zeit Sie, wenn Block treffen Sie die Sperre bereits besitzen und TryEnter sollte immer gelingen.

+0

Geben oder nehmen Sie eine Variable ;-p Für Informationen sieht es so aus, als ob sich dieses Muster in C# 4.0 ändert: http://blogs.msdn.com/ericlippert/archive/2009/03/06 /locks-and-exceptions-do-not-mix.aspx –

+0

@Marc, ja, es ist sehr aufregend, diese Veränderung zu sehen. – JaredPar

+0

@Marc, interessanter Link - danke dafür – Gambrinus

1

Das ist ein seltsames Setup. Ist 'LockObject' das gleiche wie 'lockObject'? Oder ist das ein Tippfehler? Wenn sie identisch sind, ist Ihre Einrichtung redundant, da Sie Monitor.TryEnter nicht für etwas aufrufen müssen, das Sie bereits sperren. Wenn "LockObject" ein anderes Objekt ist, dann verschieben Sie den Monitor.Exit in die Lock-Anweisung.