Kommunikation zwischen Thread und WinAPI

Hallo,

ich arbeite mich gerade in die GUI-Entwicklung mit der WinAPI ein. Dabei habe ich ein kleines Problem: Ich möchte ein Programm zur Berechnung von einigen Größen schreiben. Diese Berechnungen laufen kontinuierlich im Hintergrund in einem extra Thread. Die Ausgabe der Ergebnisse soll in Echtzeit über die GUI erfolgen. Wie funktioniert denn zwischen Thread und GUI am besten ein Informationsaustausch? Steuersignale (Parameter, Start, Stop) sollen von der GUI zum Thread übertragen werden. Zwischenergebnisse sollen vom Thread zur GUI übertragen werden und dort dann grafisch ausgegeben werden.

Eine prinzipielle Lösung würde mir reichen! Globale Variabeln wären wohl möglich, aber nicht wirklich klasse gelöst, oder?

Gruß
 
Ich habe mich bei dem Stichwort auf ein altes kleines Testprogramm gemacht. Darin geht es zwar um Interprozesskommunikation, aber zwischen Threads kannst du genauso mit Messages arbeiten. Außerdem ist es mit dem Borland Builder 6 geschrieben, zum Einlesen müsste es aber gehen. Vorneweg gleich eine kleine Korrektur: Du brauchst natürlich PostThreadMessage, die Verwendung ist aber ähnlich der von PostMessage.

Code:
#define CM_BERECHNUNG_STARTEN (WM_USER + 1)
#define CM_BERECHNUNG_BEENDET (WM_USER + 2)
#define CM_TEXT (WM_USER + 3)
Code:
void __fastcall TForm1::ApplicationEvents1Message(tagMSG &Msg,
      bool &Handled)
{       TFileStream *austausch;

        //Message-Handler
        //Taste gedrückt
        if (Msg.message == WM_KEYDOWN)
        {       switch(Msg.wParam)
                {       case VK_LEFT:   Panel2->Color=clRed; break;
                        case VK_UP:     Panel5->Color=clRed; break;
                        case VK_RIGHT:  Panel4->Color=clRed; break;
                        case VK_DOWN:   Panel3->Color=clRed; break;
                }
        }
        //Taste losgelassen
        else if (Msg.message == WM_KEYUP)
        {       switch(Msg.wParam)
                {       case VK_LEFT:   Panel2->Color=clLime; break;
                        case VK_UP:     Panel5->Color=clLime; break;
                        case VK_RIGHT:  Panel4->Color=clLime; break;
                        case VK_DOWN:   Panel3->Color=clLime; break;
                }
        }
        //Berechnung beendet
        else if (Msg.message == CM_BERECHNUNG_BEENDET)
        {       //Ergebnis ausgeben
                Label6->Caption=IntToStr(Msg.wParam);

                Handled=true;
        }
}
Code:
      PROCESS_INFORMATION temp_pi;
        STARTUPINFO temp_si;
        HANDLE slave;
        TFileStream *austausch;

        //Slave starten
        memset((void *)&temp_si,0,sizeof(STARTUPINFO));
        memset((void *)&temp_pi,0,sizeof(PROCESS_INFORMATION));
        if (!CreateProcess(     "Slave.exe",
                                NULL,NULL,NULL,false,0,NULL,
                                (GetCurrentDir()).c_str(),
                                &temp_si,&temp_pi))
        {       ShowMessage("Der Slave konnte nicht gestartet werden!");
                return;
        }

        Sleep(250);

        //Slave suchen
        slave=FindWindow(NULL,"Slave");
        
        PostMessage(slave,CM_BERECHNUNG_STARTEN,StrToInt(Edit1->Text),StrToInt(Edit2->Text));

Wenn du mehr als nur zwei Integer verschicken möchtest (mehr geht über Windows-Messages nicht direkt) dann musst du ein wenig tricksen. Verschicken einen Pointer auf des Objekt, dass du verschicken möchtest. Du musst es aber dazu in den passenden Datentyp für die Windows-Message casten, und danach natürlich wieder zurück. Das geht natürlich nur, solange sich Sender und Empfänger im gleichen Addressbereich befinden, was bei Threads im selben Prozess aber gegeben ist.

Viel Erfolg,
benediktibk
 
Eine prinzipielle Lösung würde mir reichen! Globale Variabeln wären wohl möglich, aber nicht wirklich klasse gelöst, oder?
Wenn man einen Thread über WinAPI startet, kann man auch einen optionalen Paramter übergeben:
CreateThread(..., lpParameter, ...
Dies könnte ja auch eine Struct sein, die alles nötige beinhaltet:
Code:
struct thread_com {
bool pause;
bool stop;
int input;
int output;
}
Der Austausch funktioniert dann über Zuweisungen/Auslesen der Structvariable.
Ist natürlich nur für einfache In/Outputs geeignet - sobald man mehrere Paramter gleichzeitig übergeben muss (oder auf gemeinsame Datenstrukturen zugreifen), kommt Synchronisierung ins Spiel:
mit Locks/Mutexen/Events und ähnlichem.

Hierzu sollte man dann die allgemeinen Threading-Grundlagen lesen - die WinAPI bietet dann mit "EnterCriticalSection/LeaveCrtiticalSection", "WaitFor(Single/Multiple)Object", "CreateMutex"/"CreateSemaphore" usw. genügend Möglichkeiten zur Umsetzung.

Ich wäre ehrlich gesagt hier zu faul und würde mir eine entsprechende Bibliothek suchen, die den Low-Kram für mich kapselt ;)
 
Zurück
Oben