2016-04-15 15 views
3

HintergrundMonitor.Wait zunächst gesperrt?

ich eine Anwendung zu schreiben, ich versuche, die die folgenden:

  1. ich einen Methodenaufruf zu SomeBlockingMethod machen.
  2. Diese Methode ruft Blöcke auf, bis ich SomeUnblockingMethod von einem anderen Thread aufrufen. Wenn SomeUnblockingMethod aufgerufen wird, wird die Routine in SomeBlockingMethod fortgesetzt.

Hinweis, das erste, was ich tun wird, um die SomeBlockingMethod zu nennen, und dann später werde ich die SomeUnblockingMethod nennen. Ich denke darüber nach, einen Monitor.Wait/Monitor.Pulse Mechanismus zu verwenden, um dies zu erreichen. Die einzige Sache ist, wenn man Monitor.Wait aufruft, kann man initial nicht blockieren, es sei denn die object Beteiligung wurde schon durch etwas anderes (oder mindestens nicht, dass ich weiß) von ... gesperrt, aber ich möchte blockieren, um die zuerst zu sein, was ich tun ... Also das führt mich in meine Frage ...

Frage

gibt es irgendeine Weise, die ich Monitor.Wait implementieren kann, um zunächst blockiert, bis ein Aufruf an Monitor.Pulse gemacht wird?

+0

@Sinatr vielleicht war ich verwirrend eingeben ... Lassen Sie mich dies versuchen. Wird zu dir zurückkommen. – Snoopy

+0

Sie möchten die Überladung von [Monitor.Wait()] (https://msdn.microsoft.com/en-us/library/syehfawa (v = vs.110) .aspx) verwenden, wo Sie eine Zeitüberschreitung festlegen können (z. B. [Infinity] (https://msdn.microsoft.com/en-us/library/system.threading.timeout.infinite (v = vs.110) .aspx)). – Sinatr

+0

@Sinatr ja, du hast Recht ... Da ich anfangs blockiere, ist das eine gute Idee. – Snoopy

Antwort

2

Sie können stattdessen AutoResetEvent verwenden.

AutoResetEvent ar = new AutoResetEvent(false); // false set initial state as not signaled 

Dann können Sie ar.WaitOne() verwenden, zu warten und ar.Set() wartenden Prozesse zu signalisieren.

Sie sollten Monitor verwenden, wenn Sie eine Ressource schützen möchten, oder Sie haben eine critical section. Wenn Sie einen Signalmechanismus haben möchten, klingt AutoResetEvent oder ManualResetEvent klingt eine bessere Option.

+0

Sie würden also nicht empfehlen, überhaupt Monitore zu verwenden? Warum? – Snoopy

+1

@StevieV, es ist nur eine andere mögliche Lösung. Es ist nicht nötig, zu 'AutoResetEvent' von [leichtgewichtiger 'Monitor'] (http://www.albahari.com/threading/part2.aspx#_Locking) zu wechseln, es sei denn, Sie möchten [verschiedene Prozesse synchronisieren] (http://stackoverflow.com/q/1717194/1997232). – Sinatr

+0

Ich sagte, du kannst nicht du musst. @StevieV – dotctor

1

Ich weiß nicht, was das Problem ist, aber was Sie wollen, ist bereits, wie es funktioniert:

object _lock = new object(); 

void SomeBlockingMethod() 
{ 
    lock(_lock) 
     Monitor.Wait(_lock); 
    ... // here only after pulse 
} 

void SomeUnblockingMethod() 
{ 
    lock(_lock) 
     Monitor.Pulse(_lock); 
} 

Vielleicht sind Sie SomeBlockingMethod von mehreren Stellen aufrufen, dann möchten Sie PulseAll verwenden. Oder vielleicht SomeUnblockingMethod heißt vorSomeBlockingMethod?

+0

Dazu kann die Entsperr-Methode in den 'lock'-Bereich gelangen, wenn die blocking-Methode bereits in den' lock'-Bereich eingetreten ist? Ich stelle mir vor, dass die Entblockierungsmethode in den Bereich eintreten müsste, um die Blockierungsmethode zu pulsen. Recht? – Snoopy

+0

Die Sperre wird aufgehoben, wenn Sie 'Monitor.Wait()' aufrufen, damit eine andere Methode Sperre und Impuls erhalten kann. [Lesen Sie mehr] (http://www.albahari.com/threading/part4.aspx#_Signaling_with_Wait_and_Pulse). – Sinatr