Prozessen unterschiedliche Prioritäten zuweisen



  • Hallo,

    ich habe folgendes Problem:

    Ich benutze eine Dialogfeldklasse und lasse optisch einen Countdown von 120 Sekunden anzeigen,
    der gegen Null läuft. Wenn der Countdown bei 100 ist, wird eine Funktion gestartet (Kontaktaufnahme
    zu externer Hardware...ist ja auch ganz egal). Sobald die Funktion startet, kommt mein Countdownzähler
    ins Stocken und überspringt die 109, so dass - wenn er nicht mehr zu sehr mit Rechnen beschäftigt ist,
    - er mit 108 fortsetzt.

    Wie unterbinde ich solche Sachen, d.h. wie kann ich externe Verarbeitungen von der Dartstellung
    optischer Anzeigeelemente entkoppeln?

    Ich habe schon versucht, einen anderen Timer mit der gleichen Laufzeit aufzurufen, der nichts mit der optischen Ausgabe zu tun hat...leider passiert aber genau das Gleiche.

    Danke für eure Hilfe.

    Grüße,
    Krommi



  • du kannst die priorität deines prozesses/threads etwas raufsetzen, und dann bei jeder zähleränderung ein redraw des fenster(bereich)s erzwingen.
    stichpunkte:
    - SetThreadPriority()
    - SetPriorityClass()
    - InvalidateRect()
    - UpdateWindow()
    - GdiFlush()
    - GdiSetBatchLimit()



  • hört sich gut an, komme damit aber nicht weiter.

    Ich habe zwei Timer:

    Timer 1 zählt mir einen Countdown am Bildschirm runter,
    Timer 2 ist dafür zuständig, dass bei einem Bestimmten Ereignis Daten aus einer Excel-Tabelle gelesen werden.

    Der Lesevorgang Dauert ca. 2 Sekunden, so lange kommt mein Bildschirmcountdown jedenfalls ins Stocken. Ich habe das Gefühl, als würde er in dieser Zeit Timer 1 gar nicht ausführen. Deshalb bringt es nichts, wenn ich an igend einer Stelle "UpdateWindow()" benutze.

    Kann ich denn die Priorität von Funktionen explizit heraufsetzen?



  • Arbeitest du komplett in einem Thread (Sprich: Die OnTimer()-Methode kümmert sich selber um die Hintergrund-Arbeit)? Wenn ja, hast du ein Problem, daß während dieser Arbeit die komplette Message-Queue eingefroren wird. Die Lösung heißt "Threads" (die Arbeit wird von einer eigenen Methode ausgeführt; OnTimer() startet einen neuen Thread und gibt das Kommando zurück an die MessageQueue).



  • In der OnTimer-Methode rufe ich einfach verschiedene Funktionen auf:
    - Daten auslesen
    - In Abhängigkeit der Daten weitere Funktionen ausführen...

    Du kannst damit recht haben. Das Bild wird für die Zeit, in der die Funktionen abgearbeitet werden eingefroren. Wie stelle ich das mit den Threads denn an?



  • Erstmal lagerst du die eigentliche Arbeit in eine statische Methode aus:

    UINT worker(LPVOID obj)
    {
      CMyDlg* pThis = (CMyDlg*) obj;
      ...
      // Zugriff auf deine Dialog kriegst du jetzt über pThis->...
      // Achtung: Keine fenster-relevanten Atrribute ändern, verwende stattdessen SendMessage()
    }
    

    Und dann kannst du die Timer-Funktion kürzen zu einem Aufruf:

    AfxBeginThread(worker,this);
    


  • Mit "fensterrelevante Attribute" meinst du aber keine Anzeigeelemente, oder?
    Die werden von dem Timer nämlich auch benutzt.

    Mal schauen, ob ich es richtig verstanden habe:

    UINT worker(LPVOID obj) deklariere ich als statische Methode und lagere alles, was ich in meinem 2. Timer habe in diese Funktion aus. Danach rufe ich diese Methode oder diesen "Thread" mittels AfxBeginThread(worker,this) auf.

    Verwendet man für solche Sachen grundsätzlich Threads? Habe bisher noch nie etwas damit gemacht.

    Danke und Gruß,
    Krommi



  • Krommi schrieb:

    Mit "fensterrelevante Attribute" meinst du aber keine Anzeigeelemente, oder?
    Die werden von dem Timer nämlich auch benutzt.

    Doch, genau die meinte ich - das Fenster gehört dem Anzeigethread und der nimmt es dir übel, wenn andere Threads versuchen, ihm in die Daten zu pfuschen. Aber du kannst dir eine eigene Nachricht (#define WM_WORKFINISHED WM_APP+x) definieren und dem Anzeigethread per SendMessage(WM_WORKFINISHED); mitteilen, daß du fertig bist mit deiner Arbeit - der zugehörige Message Handler zeigt dann die Ergebnisse an.

    UINT worker(LPVOID obj) deklariere ich als statische Methode und lagere alles, was ich in meinem 2. Timer habe in diese Funktion aus. Danach rufe ich diese Methode oder diesen "Thread" mittels AfxBeginThread(worker,this) auf.

    Ja.

    Verwendet man für solche Sachen grundsätzlich Threads? Habe bisher noch nie etwas damit gemacht.

    In der Regel ja - auf diese Weise bleibt dein Programm ansprechbar, während es im Hintergrund rechnet.



  • Hmm...habe alles so gemacht, bekomme aber trotzdem folgenden Fehler. Hat irgend jemand eine Idee, weshalb?

    // In CVorbereitungDialyse.h
    UINT worker(LPVOID obj)
    {
    	CVorbereitungDialyseDlg* pThis = (CVorbereitungDialyseDlg*) obj;
    
    	Reader1->ClearTable("Daten Dialysator.xls");
    	Reader2->ClearTable("Daten AVSystem.xls");
    	Reader3->ClearTable("Daten Konzentrat.xls");
    
    	return 0;
    }
    
    // In CVorbereitungDialyseDlg.cpp
    AfxBeginThread(worker, this);
    
    // Fehlermeldung
    Kompilieren...
    VorbereitungDialyseDlg.cpp
    c:\Visual C++ Projekte\Visual Studio Projects\AutoIdentification\VorbereitungDialyseDlg.cpp(325) : error C2665: 'AfxBeginThread': Durch keine der 2 Überladungen kann Parameter 1 vom Typ 'UINT (LPVOID)' konvertiert werden
            c:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\atlmfc\include\afxwin.h(4105): kann 'CWinThread *AfxBeginThread(AFX_THREADPROC,LPVOID,int,UINT,DWORD,LPSECURITY_ATTRIBUTES)' sein
            c:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\atlmfc\include\afxwin.h(4108): oder       'CWinThread *AfxBeginThread(CRuntimeClass *,int,UINT,DWORD,LPSECURITY_ATTRIBUTES)'
            bei Anpassung der Argumentliste '(overloaded-function, CVorbereitungDialyseDlg *const )'
    

    Danke und Gruß,
    Krommi



  • bei Anpassung der Argumentliste '(overloaded-function, CVorbereitungDialyseDlg *const )'

    Hast du vielleicht noch eine weitere Funktion mit dem Namen 'worker()', die mit deiner Thread-Funktion in Konkurrenz stehen könnte? Und ist worker() wirklich eine statische Methode?



  • [quote="CStoll"]

    Und ist worker() wirklich eine statische Methode?

    Genau deran lag es, hatte nochmal bei der Microsoft hilfe geschaut und dort war auch ein solches Beispiel aufgeführt, aber ohne eine statische Funktion...seltsam.

    Naja, jedenfalls funzt es jetzt.
    Vielen Dank CStoll!

    Vielleicht noch zwei Fragen für die Zukunft:
    Wie passen eigentlich Threads und OOP zusammen. Threads erinnern mich eigentlich ein wenig an prozedurale Programmierung (vielleicht liege ich auch falsch*g*).

    Hab bisher schon mehrere Grundlagenbücher zu C++ durchgearbeitet aber zu Threads bisher nur wenig gefunden. Oder wird dies wirklich erst ineressant, wenn Benutzeroberflächen ins Spiel kommen?

    Gruß,
    Krommi



  • @1: Also ich konnte mit Threads und Objekten eigentlich recht gut arbeiten (wobei ich nicht sicher bin, ob mein Stil wirklich "reines OOP" ist ;)). Und wenn du dich geschickt anstellst, kannst du auch recht gut objektorientiert threaden.

    @2: Threads werden dann interessant, wenn du mehrere Sachen parallel erledigen willst - und einer der typischen Anwendungsbereiche sind hier Benutzeroberflächen, die während der Arbeit benutzbar bleiben sollen/wollen/...


Log in to reply