existierender Thread auf kommando starten bis arbeit getan ist dann wieder warten?



  • Hallo ,

    ich will ein thread erzeigen, welche währden der ganzen Progarmmlebensdauer lebt. die Thread funktion soll eine schleife haben, welche sie auf kommande (event) starten nach ende der schleife wieder warten bis nächsten kommande kommt??

    Wie mach ich das in C# ??? sowas wie ne waitForSingleObject !?!?

    bspw

    Thread starten:

    static threadFunc(){
    
    while(true){
    
      /* Warten auf Kommando für die nächste aufgabe*/
    
      /*Aufagabe ausführen*/
    
    }
    
    }
    

    Jedesmal den Thread neu erzeigen und starten kostet zuviel zeit..



  • BorisDieKlinge schrieb:

    Jedesmal den Thread neu erzeigen und starten kostet zuviel zeit..

    dann Schau dir mal alternativ den ThreadPool an. Ist eventuell eher das was Du suchst.

    System.Threading.ThreadPool.QueueUserWorkItem(...);



  • ok danke.. hab es jetzt so gemacht, das er auf ein "EventWaitHandle" wartet.. aber uch schau mir den ThreadPool mal an.. danke:)

    Edit: Bei Threadpool handelt es sich doch um eine ansammlung mehrerer (syncronosierter) threads oder.. kann mich aber auch täuschen.



  • Gibt es ne möglichkeit nen Threadpool so zuverwenden, das nur ein Thread die Aufgaben nacheinander ausführt? Weil so wäre es ja kein "pool" mehr?

    Ich hab bspw. ne Klasse SynchronWork, welche einen thread behinhaltet.

    Über eine Funktion NewJob, will ich dise Klasse mitteilen das eine neuer Job für den thread auszuführen ist. Währende nun diese Thread die Aufgabe ausführt, kann gleichzeitig wieder NewJob ausgeführt werden. So kommt die nächste aufgabe zum start.

    Hätte mir gedachte ich mache ne queue zwischen New Job und Thread... über einen Zähler weis der Thread das noch aufgeaben vorhanden sind, und so lange in seiner Arbeitscshleife bleibt... ist das elegant oder uncool?=;)

    noch ne frage, gibt sowas nen deadlock?

    public bool Empty(){
    
    lock(...){
     return Queue....;
    }
    
    }
    

    weil hier ja ein return stattfindet, bevor die Klammer von lock geschlossen wird.



  • Ne Queue bauen ist nicht uncool. Guck dir dazu viellicht auch noch Monitor.Wait und Monitor.Notify an.

    Dein Code führt nicht zu einem Deadlock. Wießt du was ein Deadlock ist? A wartet auf B und B wartet auf A (oder größere zirkuläres Warten).

    Der Lock wird trotz return freigegeben. Das ist doch der sinn von lock().

    lock (foo) {
       ...
    }
    

    ist

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


  • Ob es zum Deadlock führt hängt davon ab, für was die ... in dem Lock stehen.



  • Mach mal ein Beispiel für die ..., die zu einem Deadlock fürhen würden.

    ----

    Die klassischste Variante, die zum Deadlock führt, sieht so aus:

    void foo()
    {
       lock (a) { lock (b) { ... } }
    }
    
    void bar()
    {
       lock (b) { lock (a) { ... } }
    }
    

    Wenn ein Thread foo ausführt und einer bar, der erste Thread a schon bekommen hat, aber noch nicht b, der zweite Thread b schon bekommen hat, aber noch nicht a, dann habe ich einen Deadlock, weil jetzt die beiden Threads auf etwas warten, was der jeweils andere Thread gelockt hält.



  • Ein

    lock(this)
    {
    }
    

    kann dann zum Deadlock führen, wenn die Instanz, die this bezeichnet, von jemand fremden als Lock Variable missbraucht wird.

    http://www.toolazy.me.uk/template.php?content=lock(this)_causes_deadlocks.xml
    http://srtsolutions.com/blogs/billwagner/archive/2007/09/09/why-lock-this-is-bad.aspx



  • Wenn's MFC wäre würde ich's so machen:

    UI thread starten
    wenn er aktiv ist sendet er mit PostMessage: I_AM_BORED
    dann schickt ihm der main-thread 'ne PostThreadMessage: DO_ANYTHING
    job erledigt - thread sendet PostMessage: I_AM_BORED
    usw. usf.

    wobei ich die jobs einfach in einer std::queue speichern würde

    aber weil ich C# nicht kann (und nicht mag) ist das eine Antwort, die ich mir eigentlich hätte schenken können :p



  • Knuddlbaer schrieb:

    http://www.toolazy.me.uk/template.php?content=lock(this)_causes_deadlocks.xml

    OK, wo ist da der Deadlock?
    Deadlock bedeutet, dass ich für immer auf einen Lock warte. Ich sehe gerade nicht, wie das bei dem Code passieren sollte.

    @Boris: Ansonsten zu der Queue:

    NewJob: Queue 'lock'en, enqueuen, queue 'pulse'n, (wird wieder entlockt)

    Eine Aufgabe entnhemen: Queue 'lock'en, wenn leer auf Queue 'wait'en, Element entnehmen, (wird wieder entlockt)

    Der Arbeiter-Thread (also dein SynchronWork, welches nicht synchron sonder asynchron arbeitet) versucht einfach die ganze Zeit in einer Schleife etwas aus der Queue zu entnehmen und es dann zu bearbeiten.



  • @Helium: ja das mit dem deadlock ahb ich verstanden danke;)

    Bei diesem Beispiel:

    A:

    lock (foo) {
       ...
    }
    

    B:

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

    würd in A eine exception lock block auftreten, würde der lock bleiben?? Bei B würde der lock auch aufgehoben werden, wenn ne exception auftritt? hab ich das richtig verstanden?



  • Ein lock-Block entsperrt immer, wenn der Block verlassen wird (egal wie!). Vgl. RAII in C++.

    Ein finally-Block wird immer ausgeführt, wenn der zugehörige try-Block verlassen wird (egal wie!).



  • hmm.. ok wenn bspw.:

    Monitor.Enter(foo);
    
    try {
       ...
    }
    catch(...){
    
    }
    
    Monitor.Exit(foo);
    

    ohne das finally, gehts doc hauch???



  • BorisDieKlinge schrieb:

    hmm.. ok wenn bspw.:

    Monitor.Enter(foo);
    
    try {
       ...
    }
    catch(...){
    
    }
    
    Monitor.Exit(foo);
    

    ohne das finally, gehts doc hauch???

    Nein. finally ist GARANTIERT das es ausgeführt wird.

    In diesem Beispiel dagegen kommt es drauf an was in den [...] passiert.

    Wenn z.B. der try-block mit einem return verlassen wird hast Du schon verloren. Oder wenn im catch nciht alle Exceptions abgedeckt werden die geworfen werden könnten hast Du schon wieder verloren.



  • Und bei dieser Variante?

    lock(...){
    
    try {
       ...
    }
    catch(...){
    
    } 
    
    }
    


  • Ein Lock wird aufgehoben, wenn der Kontrollfluss irgendwie den Block verlässt. Egal ob durch Exception, Return, aus eigener Kraft oder sonstwie. Sobald Dein Programm auf irgendeine Art und Weise nicht mehr innerhalb des Lock-Blocks ist, ist der Lock aufgehoben.

    Habe ich übrigens schon erwähnt, dass es egal ist, wie der Block verlassen wird? 🙂

    Dasselbe gilt für finally, sobald der zugehörige try-Block abgeschlossen wurde. Egal, ob durch Return, durch Werfen, durch Fangen, durch Fangen und Weiterwerfen oder auf natürlichem Wege.



  • Du hast vergessen zu erwähnen, dass es auch bei einem goto aus dem Block heraus funktioniert. 🙂


Anmelden zum Antworten