Prozessorbelastung auslesen und graphisch darstellen



  • Hallo zusammen,

    ich würde gerne für mein Programm die CPU-Belastung (evtl. auch Speicherauslastung) auslesen und diese graphisch darstellen.

    Die graphische Darstellung sollte evtl. als Balken mit dazugehörigem Prozentwert der Auslastung geschehen. Das ganze dynamisch, damit sich Anzeige auch relativ schnell auf Veränderungen reagiert.

    Des Weiteren würde mich interessieren, ob man Verhindern, bzw. ob es überhaupt vorkommen kann, dass ein Programm bei längerer Lauf- und Rechenzeit "keine Rückmeldung" gibt, obwohl kein Programmfehler besteht. Also ein "Einfrieren" aus der intensiven Berechnung erfolgen kann.

    Falls so ein Fall auftreten kann, wie steuert man dem entgegen?

    Vielen Dank für eure Hilfe.
    Liebe Grüße
    Todd



  • Zur ersten Frage kann ich nix sagen, das wird wohl nur über die WinAPI gehen.

    Zur zweiten Frage: Ja, wenn ein Programm lang andauernde Berechnungen ausführt, wird es im Task-Manager mit dem Status 'Keine Rückmeldung' angezeigt.
    Entweder fügt man an geeigneten Stellen Application->ProcessMessages() ein (in Schleifen ist es ratsam, das nicht bei jedem Durchlauf zu machen, hängt aber auch von der Laufzeit eines einzelnen Schleifendurchlaufs ab), oder man lagert die lang andauernden Berechnungen in einen Thread aus.



  • Danke für deine Antwort.

    Mein Programm führt einen Code innerhalb einer .dll aus.

    Diese dll wurde nicht in C sondern in Matlab geschrieben.
    Die eigentliche Programmausführung wird daher auch nicht von meinem C-Programm gesteuert, sondern von der externen Matlab Component Runtime (vergleichbar mit einer Java Runtime).

    Das C-Programm nimmt vom Nutzer Daten an. Wandelt diese für die .dll um und übergibt diese der .dll.

    Danach läuft die Berechnung und das C-Programm wartet auf den Rückgabewert.

    Da ich ja quasi das Hauptprogramm verlasse ist es dann dennoch möglich ProzessMessages() abzuschicken?

    Das ist leider ein Thema bei dem ich noch meine Schwierigkeiten habe. 😞

    Liebe Grüße
    Todd



  • Nein, da auf den Rückgabewert gewartet wird, hast Du keine Möglichkeit 'Application->ProcessMessages()' auszuführen. Hier hilft nur, den Aufruf der DLL in einen Thread auszulagern. Dieser läuft dann getrennt vom Applikationsthread und somit wird der Applikationsthread auch nicht mehr angehalten == Programm 'friert' nicht mehr ein.



  • Danke für deine Antwort.

    Was genau ist ein Thread und wie lege ich einen neuen an?

    Danke für die Hilfe und
    liebe Grüße

    Todd



  • Da wird es dann ein bißchen komplexer... 😉

    Du solltest Dir in der BCB-Hilfe zuerst Mal TThread ansehen. Da hast Du schon eine Menge zu lesen.



  • Hallo,

    Auch das Builder-Tutorial ist hier hilfreich.
    http://bcb-tutorial.c-plusplus.net/Thread/index.html



  • Hallo

    Auch unser Forumstutorial hat einen Abschnitt zu Threads.

    bis bald
    akari



  • Danke werde mich schlau machen. Falls dann noch Fragen offen sind, werde ich mich sicherlich wieder hier melden.

    Ich habe in der Zwischenzeit das Schlagwort "BackroundWorker" im Zusammenhang mit Threads gehört und gleich mal gegoogelt.

    Es sieht viel und hört sich nach dem was ich hier erfahren habe auch unkomplizierter an.

    Hat jemand damit schon Erfahrungen gemacht und kann den Aufwand zwischen dieser und der Thread Methode abschätzen?

    Hier der Link zum Thema: (falls es jemanden interessiert 🙄 )

    http://msdn2.microsoft.com/de-de/library/8xs8549b(VS.80).aspx

    Liebe Grüße
    Todd



  • ASPX ist doch .NET, also im BCB nicht verwendbar. Oder übersehe ich etwas?



  • Nein, du übersiehst nichts. 🙂



  • @Todd:
    Wie bringst du MatLab und ne graphische Oberfläche erstellt mit Borland unter einen Hut? Ist mal so ne Interessefrage. 😃



  • Hallo,

    danke für das Interesse.

    Das ist eigentlich ganz einfach.
    Tauschen wir unser Wissen auf. Du erklärst mir wie ich das mit den Multi-Threads mache und ich erkläre wie die Einbindung von Matlab Code in ein C-Programm (BCB) funktioniert. 😋

    Liebe Grüße
    Todd



  • Kann ich machen. Also prinzipiell ist mir die ganze Nummer mit C/C++ und MatLab ja klar. Zu mindest wenn man ein Mex-File schreiben will, dass dann von MatLab über die mexFunction(...) aufgerufen werden soll.
    Nur die Nummer mit der graphischen Oberfläche von Borland ist mir jetzt nicht ganz klar.

    Tja, für das Multithreading kannst du entweder die Borland-Klasse TThread (keine Ahnung, wie die funktioniert. Hab sie noch nie verwendet.) benutzen oder du schaust dir die Winapi mit CreateThread und Konsorten an, welche ich nun wieder rum verwende oder auch verwendet habe um Multithreading unter Matlab möglich zu machen.



  • Hierfür sollte ein Standard-TThread völlig ausreichend sein. Hier gibt es auch irgendwo ein Tutorial zu TThread, ich bin nur zu faul den Link zu suchen. 😉

    Schau Dir das Tutorial an... Bei Problemem helfen wir gerne weiter.

    Grüße Joe_M.



  • Hallo Joe_M,

    da nehm ich dich dann aber beim Wort. Bin mir sicher, dass ich auch nach dem Durchlesen der Tutorials und der Hilfe meine Schwierigkeiten haben werde.
    Und dann aber bitte keine Verweise mehr auf Sachen zum Lesen. 🙄

    Okay, wie fügt man Matlab Code in ein C-Projekt ein.
    Beispiel am BCB6:

    1. Schritt: Schreiben des m-Files unter Matlab, z.B.
    
                function y = foo(x)
                y = 2*x;
    
    2. Schritt: Kompilieren des m-Files aus Auslagern des Codes in eine C-Shared 
                Library; Auf der Kommandozeile:
    
                >> mcc -W lib:foo -T link:lib foo.m
    
       Jetzt entsteht: foo.h, foo.c, foo.ctf, foo.dll
       foo.h und foo.dll müssen später ins BCB Projekt inkludiert werden und 
       foo.ctf muss später im Anwenderverzeichnis liegen!
    
    3. Schritt: Das BCB Projekt
    
       Um die .dll ansprechen und ausführen zu können, muss auf dem späteren System
       unbedingt eine Matlab Component Runtime installiert sein, sowie das ctf 
       Archiv im Anwenderverzeichnis vorhanden sein. Die MCR wird standardmäßig zu 
       jeder Matlab Version mit Compiler Toolbox mitgeliefert und kann weitergeben
       werden.
    
       Außerdem müssen die Verzeichnisse <matlabroot>extern\include 
       sowie                             <matlabroot>extern\lib\win32\borland
       mit unter den Projektoptionen eingebunden werden!
    
       Alle Ein- und Ausgabeparameter, ganz egal welchen Typs sie sind(Double, int,
       CellArray, StructArray etc.) haben in C den mxArray Typ.
    
    Zu BCB
    
    include <vcl.h>
    #pragma hdrstop
    
    #include "Unit1.h"
    #include "foo.h"
    //---------------------------------------------------------------------------
    #pragma package(smart_init)
    #pragma resource "*.dfm"
    void display(const mxArray* in);
    TForm1 *Form1;
    //---------------------------------------------------------------------------
    __fastcall TForm1::TForm1(TComponent* Owner)
            : TForm(Owner)
    {
    }
    //---------------------------------------------------------------------------
    
    void __fastcall TForm1::Button1Click(TObject *Sender)
    {
     //Aufruf der MCR
       mclInitializeApplication(NULL,0); 
    
     //Deklaration der Ein- und Ausgabeparameter
       mxArray *in1;
       mxArray *y = NULL;
    
     //Beispieldaten zur Eingabe   
     double data[] = {1,2,3,4,5,6,7,8,9,10};
    
     //Anlegen eines Spaltenvektors mit Doublewerten der Dim (10,1)
     in1 = mxCreateDoubleMatrix(10,1,mxREAL);
     memcpy(mxGetPr(in1), data, 10*sizeof(double));
    
     //Laden der .dll
     if (!fooInitialize())
     {
      ShowMessage("Fehler beim Laden der dll");
      return;
     }       
    
     //Aufruf der Funktion mlfFoo und Übergabe Ein- und Ausgabeparameter
     mlfFoo(1, &y, 1, &in1);
    
     //Zugriff auf den Rückgabewert
     display(y);
    
     //Destroy Array, Speicher freigeben
     mxDestroyArray(y); y=0;
     mxDestroyArray(in1); in1=0;
    
    }
    //---------------------------------------------------------------------------
    void __fastcall TForm1::FormClose(TObject *Sender, TCloseAction &Action)
    {
     //Terminiere die .dll und MCR
     fooTerminate();
     mclTerminateApplication();   
    
    }
    //---------------------------------------------------------------------------
    void display(const mxArray* in)
    {
        int i=0;
        int r=0; 
    
        //Zeiger auf das mxArray (Rückgabewert)
        double *data; 
    
        //mxGetM = Anzahl der Zeilen im Rückgabewert
        r = mxGetM(in);
    
        //Zeiger auf den Vektor
        data = mxGetPr(in);
    
        //Ausgabe der Daten 
        for( i = 0; i < c; i++ )
        Form1->StringGrid1->Cells[0][i]=data[i];
    
    }
    

    Das wars eigentlich schon. Die eigentliche Berechnung erledigt dann die MCR.
    Mann muss sich nur noch um die korrekte Deklaration der Ein- und Ausgabewerte kümmern und um die korrekte Übergabe etc.

    Das ganze funktioniert in gleicherweise mit Strukturen, Cell-Arrays, Matrizen etc...

    Und für genau so eine Berechnung bräuchte ich einen zweiten Thread.
    Beginn vor dem Aufruf der Funktion mlfFoo, da er dann in die .dll geht und auf den Rückgabewert wartet.

    Hoffe ich konnte die ganze Thematik einigermaßen verständlich erklären.

    Liebe Grüße und schönes WE
    Todd



  • Aha, gut auf dem Weg hab ich mit Matlab noch nie gearbeitet. Ich denke mal, das ist sinnvoll, wenn man Simulationsberechnungen oder komplexere mathematischen Berechnungen machen will. Da Matlab solche Sachen ja schon implementiert hat, brauch man sich dann nicht die Arbeit machen und alles selbst schreiben.

    Dann hier mal der WinApi-Weg:

    DWORD stelleBerechnungAn(LPVOID ThrParam); //Aussehen einer startfähigen Funktion
    
    //zum Starten dann selber, braucht man
    
    HANDLE hThr = NULL;
    DWORD ThrId = 0;
    
    hThr = ::CreateThread(NULL, 0, stelleBerechnungAn, NULL, 0, &ThrId);
    if (hThr == INVALID_HANDLE_VALUE)                 // ^
    { /*Fehlerbehandlung*/ }                          // |
                                //falls Parameter in die Funktion sollen, dort
                                //den Zeiger übergeben
    

    Eleganter wäre es allerdings die Funktion als Member einer Klasse zu implementieren und die Klasse dann selbst als Parameter zu übergeben.
    Wichtig ist dann nur das stelleBerechnungAn(...) static ist.

    Na vielleicht hilft's dir ja. Wenn du die TThread-Klasse nimmst, musst du dich dann wohl an die anderen halten. 😃



  • Hallo,

    ich hab mich jetzt mal dazu entschlossen die WinAPI zu benutzen.
    Scheint mir irgendwie besser zu gefallen.

    //---------------------------------------------------------------------------
    
    #include <vcl.h>
    #pragma hdrstop
    
    #include "Unit1.h"
    #include "windows.h"
    //---------------------------------------------------------------------------
    #pragma package(smart_init)
    #pragma resource "*.dfm"
    TForm1 *Form1;
    //---------------------------------------------------------------------------
    __fastcall TForm1::TForm1(TComponent* Owner)
            : TForm(Owner)
    {
    }
    //---------------------------------------------------------------------------
    DWORD WINAPI MyThread( LPVOID lpParam ) 
    {
     for (int i=1;i<100000;i++)
     Memo1->Lines->Add("Neuer Thread");
    }
    void __fastcall TForm1::Button1Click(TObject *Sender)
    {
     LPDWORD dwThreadId;
     CreateThread(NULL, 0, MyThread, NULL, 0, NULL);
    }
    //---------------------------------------------------------------------------
    void __fastcall TForm1::Button2Click(TObject *Sender)
    {
     ShowMessage("HauptThread");        
    }
    //---------------------------------------------------------------------------
    

    Ist das jetzt schon mal so okay? Es funktioniert jedenfalls. Kann Button2 betätigen, während die Eintragung in das Memofeld noch stattfindet.

    Also ist jetzt erstmal ein kleiner Ansatz, bin aber schonmal begeistert, dass es bis jetzt zumindest funktioniert. 😮

    Zum Thema Matlab Code:

    Es eignet sich hervorragend zur mathematischen Berechnungen und in Folge dessen auch zur Programmierung. Für welche, die wie ich Matlab schon seit Jahren nutzen ist es zehnmal leichter damit umzugehen als eine Programmierung in C++ zu starten.

    Deshalb nutze ich die Schnittstelle zwischen C und Matlab. Die Programmierung im BCB hat für mich nur den Sinn, eine schöne, bedienerfreundliche und unabhängige Software zu entwickeln.

    Danke schonmal für eure Hinweise und liebe Grüße
    Todd



  • Hmm, also das sieht sehr einfach gehalten aus. Du solltest wenigstens eine Fehlerabfrage nach der Erstellung einbauen. Kann ja sein, dass irgendwas bei der Erstellung schief geht und so merkst du's nicht mal.
    Ausserdem ist es auch sinnvoll sich ein Handle von dem Thread zu holen, so dass du beim Schliessen deiner Anwendung den Thread über TerminateThread(...) abschiessen kannst. Allerdings sollte das wirklich nur der letzte Ausweg sein.

    Ich muss dir dringend davon abraten, so unsauber einen Thread zu implementieren, da du so völlig die Kontrolle über den Thread aufgibst. Aber ich geh mal davon aus, dass das jetzt nur Beispielcode ist und du nachher in deinem Programm etwas sauberer arbeiten wirst. 😉



  • Ja klar,

    das war jetzt erstmal ein erster Versuch.
    Das da noch Fehlerabfragen etc. eingebaut müssen, ist mir bewusst.

    Aber der prinzipielle Aufbau ist richtig oder?
    Terminiert sich der neue Thread automatisch nach der Bearbeitung oder muss man zwingend den zweiten Thread schließen, nach dem er abgearbeitet ist?

    Liebe Grüße
    Todd


Anmelden zum Antworten