Timer oder Thread?



  • Guten Morgen,
    ich hab da mal so ne allgemeine Frage!
    Wenn ich ein Programm hab, und das soll etwas solange tun, bis ich dem Programm sage jetzt ist gut gewesen, was ist da besser zu benutzten? nen Timer oder nen Thread (in dem eine Schleife läuft) ??

    Ich würde sagen nen Thread oder?



  • Thread

    Timer sind nett für einen Refresh von Dialogen o.ä., aber man kann damit keine ernsthafte Synchronisation aufbauen.

    Übrigens sollten Schleifen in Threads immer zwischendurch mal die Rechenzeit wieder abgeben... sonst blubbert der Thread mit Volldampf dahin und klaut dem System sämtliche freie Rechenzeit. Zwar kommt der Rest auch weiterhin dran, aber die Systemlast wird ohne Umschaltung deutlich höher.

    [ Dieser Beitrag wurde am 13.08.2002 um 08:19 Uhr von Marc++us editiert. ]



  • @Marc++us : danke hatte es mir auch schon fast gedacht!
    du sagtest bei schleifen in threads rechenzeit abgeben 😕
    Wie bewerkstellige ich das?? Ich weiss wie ich nen Thread erstelle, aber davon hab ich noch nix gehört..wäre um ne erklärung dankbar 🙂



  • Anleitung (so erstelle ich einen Thread):

    1. Erstelle eine Klasse abgeleitet von WinThread
    2. Erstelle folgende "public´s"

    virtual int Run();
    CHauptDlg* m_dialogvar;
    CHauptDlg* m_pOwner;
    void SetOwner(CHauptDlg* pOwner) { m_pOwner = pOwner; };
    

    3. Includiere die Hauptklasse in der Threadklasse

    #include "HauptDlg.h";
    

    4. (Hauptklasse) Nimm die Threadklasse auf

    class CDeinThread;
    

    5. Erstelle nen (?pointer) zum Thread

    CDeinThread* m_xDisplayThread;
    

    6. Nun kannst du den Thread wie folgt aufrufen

    m_xDisplayThread = (CDeinThread*)
    AfxBeginThread(RUNTIME_CLASS(CDeinThread), NULL,
        0, CREATE_SUSPENDED);
    
    m_xDisplayThread->SetOwner(this);
    m_xDisplayThread->ResumeThread();
    

    So das sollte es gewesen sein..



  • Wenn Marc++us noch was zur Rechzeitfreigabe gepostet hat, werd ich diesen Thread mal in die FAQ packen



  • Aber Du setzt mich jetzt nicht unter Druck, oder?

    Kurzer Exkurs:

    Wenn man in einem Thread Schleifen der folgenden Form hat:

    while (anything())
    {
       do_something();
    }
    

    Passiert ein unschöner Effekt: der Thread gelangt nie in den "Ready-State" und das System teilt ihm daher alle noch freie Rechenzeit zu. Die Systemlast knallt hoch auf 100%.

    Das kann notwendig sein, wenn der Thread wirklich mit Hochdruck etwas erledigen muß.

    Oftmals ist dies aber auch eine Fehlkonstruktion, weil die Schleife auf etwas warten oder die Abfrage gar nicht so oft ausführen muß. In solchen Fällen wirkt z.B. ein WaitForSingleObject

    while (anything())
    {
       do_something();
       // warte nun auf ein Synchronisationsobjekt
       WaitForSingleObject(...);
    }
    

    oder ein Sleep

    while (anything())
    {
       do_something();
       // setzt Thread auf Ready
       Sleep(0);
    }
    

    Wunder. Einfach mal ausprobieren und die Rechenlast vergleichen. Die Lösung mit WaitForSingleObject ist etwas komplizierter, da man sich hier schon überlegen muß worauf man wartet - aber selbst wenn man einfach eine for-Schleife über 100000 Datensätze drüberrutschen läßt in dem Thread, ist so ein kleines Sleep an der richtigen Stelle eine Wohltat für die Systemlast.

    Ich empfehle an dieser Stelle einige Experimente, um einen Eindruck vom Unterschied zu bekommen.



  • Apropos Rechenzeit abgeben:

    Während man in in einer Schleife auf die Beendigung eines Threads wartet, der mit recht geringer Priorität laufen soll, kann man das Abfragen des Beendigungs-Events mit einem TimeOut versehen, etwa folgendermassen:

    while( WaitForSingleObject( hEventThreadBeenden, 10) == WAIT_TIMEOUT)
    {
      // do something
    }
    

    Wenn die Priorität des Threads manuell mit SetPriority auf unter 'Normal' gestellt wurde, wüßte ich allerdings nicht, wozu man in Zählschleifen oder so noch Rechenzeit abgeben sollte. Dies macht das System auf Basis seiner Zeitscheibenautomatik von selber.
    Außerdem hat ein Thread innerhalb eines Prozesses immer eine geringere Priorität als der Prozess.



  • Alles Klar...
    ne ich setzt dich jetzt nicht unter Druck.. 😉



  • Schon richtig, die Systemlast geht hoch auf 100%, doch da ich den Thread meist in der Priorität tiefer stufe, übernimmt das System automatisch, wann es den Thread kurzzeitig abschaltet.

    Sleep ist vielleicht für DB-Abfragen ganz gut, aber anderes Beispiel:

    for( int i=0; i<100000; i++)
    {
      a += abs(b); // Funktion mit wenig Rechenzeit
    }
    

    Normal braucht diese Schleife ein paar Millisekunden. Inklusive eines Sleeps geht das schon mal auf ein paar Sekunden hoch. Da lasse ich doch das System lieber ein paar Millisekunden warten, statt mehrere Sekunden auf die Lösung der Schleife zu warten.



  • RenèG:

    Ich denke das Marc++us nicht das verwenden von Sleep(0) in einer Rechenschleife meinte sondern in der Warteschleife.
    In manchen Situationen hilfte es schon.
    Habe ein Programm welches 20 Threads hat.
    Jeder einzelne wartet auf einen Netzwerkconnect und empfängt eine Soundstream.
    Im Thread wird dann eine Spracherkennung durchgeführt und das Cleartextergebniss wieder zurückgesendet.
    Hier hat an einigen Stellen ein abgeben des Zeitfenstern wunder gewirkt.



  • Mhhh, also ich hols jetzt nochmal wieder auf
    Ich check mit dem Thread und ner verschleiften schleife 😉 ob eine datei aktuallsiert worden ist, das ganze sieht so aus:

    CString check,stat;
    while(m_pOwner->checker != TRUE)
    {
    //setlocale(LC_ALL, "German");
        CFileStatus status;
        CFile file;
        CString pfad;
        pfad = m_pOwner->setup.m_pfad;       
        CTime filetime;
        if(file.GetStatus(pfad,status))
        {
            filetime = status.m_mtime;
            stat = filetime.Format("%d.%m.%Y - %H:%M:%S");
        }
        if(check != stat)
        {
            m_pOwner->m_log.SetCurSel(m_pOwner->m_log.AddString(m_pOwner->zeit +(" : ")+stat));
            check = stat;
        }
    
        Sleep(0);
    }
    

    So nun ist die Systemauslastung aber dann auf 100 (aber es läuft anscheind noch alles gut)
    So das kanns ja aber nicht sein.... Und es von grosser Wichtigkeit das das Programm diese Datei ständig Prüft, das hört eigentlich nie auf...
    Also??
    Was kann ich tun?? Hat jemand Ideen??

    der code steht in einem stinknormalen thread 🙂

    [ Dieser Beitrag wurde am 04.09.2002 um 15:30 Uhr von C-O-M-M-A-N-D-E-R editiert. ]



  • Hallo Commader,

    also für diesen Zweck wäre meiner Meinung nach auch ein Timer gegangen. Aber ein Thread ist natürlich schon eleganter.

    Du prüfst deine Datei im Sekundenbereich. Also nehme ich mal an, dass es sooo dermaßen zeitkritisch nicht ist. Was hindert dich daran mal

    Sleep(500)
    

    statt

    Sleep(0)
    

    einzubauen um zu sehen, was dann mit der Auslastung passiert?

    Nur so als Idee...

    Grüße, Volle.



  • Super!!! danke Volle.... das hat meine Systemauslastung enorm runtergebracht!!

    Erst 100% und nun nur nopch 4-6 % *freu*

    spitzenmässig....

    thx
    commander



  • *mitfreu* + *AufDenLorbeerenAusruh*

    😃

    Grüße, Volle.



  • Warum überwachst du nicht den Ordner. Wenn sich etwas ändert dann erst ob sich das File geändert hat

    FindFirstChangeNotification



  • Wieso soll ich den Ordner überwachen??
    Ist doch einfacher wenn ich direkt die File überwache!! Das funktioniert auch schon einwandfrei, mein Problem ist halt nur noch das einlesen 😉



  • Das Überwachen muß du aber in einer SChleife realisieren.
    Das Überwachen nicht da dir Windows eine Message sendet wenn sich was ändert.
    Somit braucht dein Programme in diesem Moment 0 Resourcen.



  • Mhhhh wäre ne Überlegung wert.... nicht schlecht..vielen Dank..



  • Das Thema ist zwar schon uralt, aber trotzdem noch eine Frage:

    Ich haben eine Thread-Klasse von CWinThread abgeleitet (habe also MeinThread.h und MeinThread.cpp) und möchte die jetzt in CAppView einbinden.
    Dazu habe ich in der MeinThread.h meine AppView.h includiert (um einen Member-Pointer auf die CAppView anzulegen.

    Nun muss ich ja in meine AppView die MeinThread.h includieren, um da wiederum einen Zeiger auf meinen Thread einzubauen.

    Danach erhalte ich aber Fehlermeldungen angro - was sicher an dem gegenseitigen includieren liegt oder?
    Wie löse ich dieses Problem?

    Danke und Gruß
    Chris



  • Hi,
    ja das mit dem gegenseitigen includieren ist machnmal zum verzweifeln.

    Versuch mal folgendes:
    Includiere in Deine AppView NICHT MeinThread.h, sondern mach in AppView.h eine Vorwärtsdeklaration. Dazu brauchst Du nur zu schreiben:

    //AppView.h

    class MeinThread;

    class AppView
    {
    //Methoden und Variablen
    .......
    ......

    }

    Jetzt kennt AppView Deine Thread-Klasse, ohne dass Du sie includieren musst! 😃

    (Falls es nicht geht, mach es umgekehrt. Mach eine Vorwärtsdeklaration der Klasse AppView in MeinThread.h)


Anmelden zum Antworten