Wie eine Methode schreiben, die nicht sofort returned?
-
Hallo!
Ich frage mich wie man eine Methode schreibt, die nicht sofort returned, sondern z.B. wartet, dass eine best. operation beendet wird, dabei aber nicht auf 100% CPU Auslastung geht.
Nehmen wir mal an wir haben eine Methode, die einen neuen Thread erstellt um eine längere Operation auszuführen. Wenn sie den Thread gestartet hat, könnte sie theorätisch zurückgeben. Was aber wenn ich haben will, dass sie erst returned wenn der Thread fertig ist (ich weiß, das ist jetzt etwas unsinnig, aber es ist nur ein Beispiel)? Würde ich so etwas mit Sleep() lösen und wenn ja, wie lange sollte die Zeitspanne sein?
Könnte es zum Beispiel so aussehen?private void Foo() { Thread t = new Thread(new ThreadStart(DoSomething)); t.Start(); while (t.IsAlive) Thread.Sleep(100); // sind 100 ms empfehlenswert oder nicht? }
Ein zweites Beispiel für die Frage wäre die WinAPI Funktion GetMessage(), die gibt auch erst zurück, wenn es einen neue Message gibt.
Danke im Vorraus!
-
Was du brauchst, ist ein Monitor. Du musst den Monitor eines beliebigen Objekts mit lock( object ) betreten, darin System.Threading.Monitor.Wait(object). Der andere Thread macht Monitor.Pulse(object), sobald er fertig ist.
In deinem Beispiel kann man auch nen asynchronen Delegate-Aufruf verwenden.
-
Also schon mal Danke.
Mich würde aber auch interessieren was da eigentlich im Hintergrund passiert, wie sieht eine Funktion aus, die erst zurückgibt, wenn etwas bestimmtes eintritt?
-
Du sagst Monitor.Wait(myObject) und der Thread, der das aufruft, gibt die Kontrolle über den Monitor von myObject auf und kriegt vom Scheduler keine Rechenzeit mehr. Wenn "etwas bestimmtes eintritt", dann signalisiert ein anderer Thread das dem Scheduler entsprechend. Monitor.Pusle(myObject) weckt einen der Threads, die an myObject warten, PulseAll() weckt alle.
Der Monitor von .Net ist ein Mesa-Typ, das heißt die aufgeweckten Threads versuchen alle, den Monitor von myObject wieder zu betreten, was aber erst klappt, nach dem der weckende Thread ihn verlassen hat. Wenn der weckende Thread sein lock gleich nach dem Pulse aufgibt, kann man also sagen, die geweckten Threads laufen sofort weiter.
Mehr Hintergrund: http://de.wikipedia.org/wiki/Monitor_(Informatik)
Du kannst dich auch von meinem minimalistischen ThreadBlocker inspirieren lassen:
using System.Threading; namespace util { /// <summary><c>ThreadBlocker</c> werden benutzt, um Threads bis zum Eintreten eines /// Ereignis schlafen zu legen. Diese Klasse ist thread-safe.</summary> public class ThreadBlocker { /// <summary>Blockiert den aufrufenden Thread so lange, bis ein anderer Thread /// ihn wieder aktiviert.</summary> public void Wait() { lock( monitoredObject ) { Monitor.Wait(monitoredObject); } } /// <summary>Weckt einen der schlafenden Threads wieder auf. Falls im Moment /// keine Threads durch diesen Blocker angehalten wurden, geschieht nichts. /// </summary> public void PulseOne() { lock( monitoredObject ) { Monitor.Pulse(monitoredObject); } } /// <summary>Weckt alle schlafenden Threads wieder auf. Falls im Moment keine /// Threads durch diesen Blocker angehalten wurden, geschieht nichts.</summary> public void PulseAll() { lock( monitoredObject ) { Monitor.PulseAll(monitoredObject); } } private readonly object monitoredObject = new object(); } }
Weil du das GetMessage() angesprochen hast: Ich kann dir auch ne BlockingQueue geben, die den entnehmenden Thread so lange blockiert, bis was drin ist.
-
Optimizer schrieb:
Was du brauchst, ist ein Monitor. Du musst den Monitor eines beliebigen Objekts mit lock( object ) betreten, darin System.Threading.Monitor.Wait(object). Der andere Thread macht Monitor.Pulse(object), sobald er fertig ist.
In deinem Beispiel kann man auch nen asynchronen Delegate-Aufruf verwenden.
quatsch. is gibt in java ne eigene methode um auf die beendigung eines threads zu warten. da muss man nix explizit locken.
-
kenner der thread szene schrieb:
Optimizer schrieb:
Was du brauchst, ist ein Monitor. Du musst den Monitor eines beliebigen Objekts mit lock( object ) betreten, darin System.Threading.Monitor.Wait(object). Der andere Thread macht Monitor.Pulse(object), sobald er fertig ist.
In deinem Beispiel kann man auch nen asynchronen Delegate-Aufruf verwenden.
quatsch. is gibt in java ne eigene methode um auf die beendigung eines threads zu warten. da muss man nix explizit locken.
Ich nehme an, du wolltest .Net schreiben. Ich habe tommazzo so verstanden, dass das Warten-auf-Threadende nur ein Beispiel ist und er eine generelle Lösung wollte um Threads schlafen zu legen. In jedem Fall ist es aber trotzdem kein "Quatsch" sondern ein super-einfache Lösung.
-
gibts nicht sowas wie mythread.join()?
-
Ja, ich denke, das meinte der Kenner.
-
Optimizer schrieb:
kenner der thread szene schrieb:
Optimizer schrieb:
Was du brauchst, ist ein Monitor. Du musst den Monitor eines beliebigen Objekts mit lock( object ) betreten, darin System.Threading.Monitor.Wait(object). Der andere Thread macht Monitor.Pulse(object), sobald er fertig ist.
In deinem Beispiel kann man auch nen asynchronen Delegate-Aufruf verwenden.
quatsch. is gibt in java ne eigene methode um auf die beendigung eines threads zu warten. da muss man nix explizit locken.
Ich nehme an, du wolltest .Net schreiben. Ich habe tommazzo so verstanden, dass das Warten-auf-Threadende nur ein Beispiel ist und er eine generelle Lösung wollte um Threads schlafen zu legen. In jedem Fall ist es aber trotzdem kein "Quatsch" sondern ein super-einfache Lösung.
Nein, ich meine java. der OP wollte einfach auf einen Thread warten. Dafür gibt es die Methode join(). Da muss man nicht erst groß rumcoden und bereiche locken ;-))
-
Die gibt's ja in .Net auch.
-
Jetzt wird mir einiges klarer. Das heißt immer wenn eine Funktion pausiert werden muss bis Ereignis x eintritt, wird sie über einen Monitor direkt am Thread Scheduler angehalten. Ich nehme an, dass es im Fall von GetMessage() in etwa so sein wird, dass GetMessage() irgendeinen Monitor auf Wait setzt und Windows beim hinzufügen einer Message den Pulse sendet.
Stichwort Thread.Join(): Ich weiß, dass es diese Methode gibt, mich hat allerdings vielmehr interessiert was dahinter steckt.
Vielen Dank nochmal!