Eigene Ereignisse definieren,auslösen & abfangen

Hallo,

ich möchte in einem C++ Programm eigene Ergeignisse definieren, auslösen und abfangen.
Ich weiss jedoch absolut nicht, wie ich dies anstellen soll. Kann mir jemand ein kleines Beispiel geben?

Viele Grüße aus Hamburg,

Jens Hibbeler
 
moin


Alles was du brauchst ist doch ne Callback Routine?!
Dann kannst eigene Nachrichten dfinieren und aufrufen.


mfg
umbrasaxum
 
Ich denke dazu eignen sich virtuelle Methoden ganz gut..
Was du ausserdem noch brauchst ist ein Thread.
Da ich nicht weiß für welches Betriebssystem du entwickelst, sollte dir
folgender Halbpseudocode das ganze viell ein bisschen verdeutlichen:

Code:
#include <iostream>

using namespace std;

class KeyListener{
    virtual void onKeyPressed(char keycode) = 0;
};
    
class MyKeyListener : public KeyListener{
    void onKeyPressed(char keycode){
        cout << "Key with key code: " << keycode << " pressed!" << endl;
    }
};      

//wird in einem neuen Thread ausgeführt
void threadfunction(KeyListener* k){
    char keycode = warteAufEreignissVonKeyboard();
    k->onKeyPressed(keycode);
}

int main(){
    KeyListener* k = new MyKeyListener();
    //starte den neuen Thread
    starteThread(threadfunction, k);
    //Hier geht der Haupthread weiter
    delete k;
}

Gruß

RedWing
 
Zuletzt bearbeitet:
Hallo,

ich glaube ich habs verstanden -der Pseudocode war seht gut. Nur wie definiere ich das genau? Ich habe als Entwicklungsumgebung Borland C++ Builder 6 und als Betriebssystem Windows XP. Wer sich mal die Dokumentation vom Borland Builder dazu zur Hilfe nimmt wird schwer enttäuchst sein, die ist nun virklich zu vernachlässigen.

Ich habe mal in anderen Programmen gewühlt und gesehen, dass es irgendwie mit...

Code:
#ifdef WIN
long FAR PASCAL _export WinSocketWndProc ( HWND hWnd,
			                         unsigned int nMsg,
			                         WORD    wParam,
			                         LONG     lParam  )
#else
LRESULT WINAPI WinSocketWndProc ( HWND hWnd,
			            UINT nMsg,
			            WORD wParam,
			            LPARAM lParam  )

...zu tun haben muss (also hier um ein WinSocket Ereignis zu definieren).

Ich denke mal, die Klasse KeyListener muss noch von irgeneinder allgemeinen Listener Klasse abgeleitet werden? In der überschreibe ich dann die Listener-Methoden und defniere meine eigenen? Im Haupt-Thread (Main Methode) tritt dann ein Ereignis ein (hier Tastaureingabe), dass dann im Nebenthread abgenfangen wird?

Gibt es vielleicht irgendwo ein Tutorial oder ähnliches wo ich das genauer nachlesen kann? Oder nen Tipp, wonach ich genau suchen müsste?

Viele Grüße,

Jens Hibbeler
 
Hallo,

das Problem , warum ich da so kompliziert machen muss ist, dass ich ein Programm habe, dass asynchron kommuniziert. Dies soll nun ein Protokoll benutzen das synchron kommuniziert. Da das Programm ja von eienr asynchronen Kommunikation ausgeht, besteht das Problem darin, dass bestimmte Code-Abschnitte nicht mehr durchlaufen werden, denn das Programm warten muss bei synchroner Kommunikation auf die Antwort der Nachricht warten. Ich habe versucht die Kommunikation mittels eines Threads zu entkoppeln, jedoch sprint der Thread irgendwo ins Program rein und alles läuft schief.
Die einzige Möglichkeit besteht also mittels eines Events nach der erfolgreichen Kommunikation im Programm weiterzumachen.
Leider geht es nicht einfach mittels Join auf das Ende des Threads zu warten, da auch dann das Programm blockiert. Bleiben also nur die Events....

Ich abe mir mal dein Beispiel genommen und das versucht auf meine Problematik anzupassen:

Code:
#include <iostream>
#include <pthread.h>

using namespace std;

class ThreadListener{
    public : virtual void threadIstFertig(void) = 0;
};

class MyThreadListener : public ThreadListener{
    void threadIstFertig(void){
        cout << "Thread ist fertig, mache nun weiter im Haupt-Thread" << endl;
    }
};


int zahl1=1;
int zahl2=2;

//wird in einem neuen Thread ausgeführt
void * threadFunction(void * parameter){
     //Berechnung durchführen und Event auslösen...
     zahl1+=zahl2;

    return NULL;
}

int main(){

    ThreadListener* tl = new ThreadListener();

    //starte den neuen Thread
   pthread_t threads[1];
   pthread_create(&threads[0], NULL, threadFunction, NULL);

   bool warteAufEreignisvonThread=true;

    //Hier geht der Haupthread weiter
    if (event threadistfertig)
    {
          tl->threadIstFertig();
          cout << "Ergebnis: " << zahl1 << endl;
    }
   delete tl;
}


...so in etwa. Jedoch weiss ich nicht, wie ich das Event definiere, auslöse und abfange.

Viele Grüße,

Jens
 
Ich bin durch zufall auf ein bissel Code gestoßen, das mir weitergeholfen hat, das ursprüngliche Problem jedoch nicht komplett löst.
Erst einmal der Code:
Code:
#include <iostream>
#include <pthread.h>
#include <windows.h>

HANDLE threadFertig;

//Mein Neben-Thread
DWORD WINAPI ThreadFunktion(LPVOID param)
{
        for(int i=0; i<10; i++)
        {
          std::cout << "Hallo von Neben-Thread" << std::endl;
        }
        //Haupt-Thread benachrichtigen
        SetEvent(threadFertig);

return 0;
}

//Mein haupt-Thread
int main()
{
        //Event erstellen
        threadFertig=CreateEvent(0, FALSE, FALSE, "ThreadFertig");

        //Thread abschicken
        DWORD threadId = 0;
        HANDLE threadHandle = CreateThread(0, // keine Security
                                        0, // default-Stack
                                        ThreadFunktion,
                                        0, // kein Parameter
                                        0, // normal erzeugen
                                        &threadId // threadId
                                     );
        //Simulation: hier geschieht was
        for(int i=0; i<10; i++)
        {
          std::cout << "Hallo von Haupt-Thread" << std::endl;
        }

        DWORD wait = WaitForSingleObject(threadFertig, INFINITE);

        //Simulation: hier geschieht was
        //Wartet der Haupt-Thread
        for(int i=0; i<10; i++)
        {
          std::cout << "Es geht weiter.." << std::endl;
        }

        //Hier wichtig für mich: Thread hat signalisiert, dass er fertig ist.
        if(WAIT_OBJECT_0 == wait)
        {
                 std::cout << "Thread beendet" << std::endl;
        }

        //Damit sich die Konsole nicht sofort wieder schließt..
        int temp;
        std::cin >> temp;

return 0;
}

Die Methode WaitForSingleObject(threadFertig, INFINITE) wartet zwar in Haupt-Thread, doch muss ich dann doch immer noch nachschauen, ob der Thread fertig ist. Auch das will ich vermeiden. Also am besten wäre es, wenn mir der Nebenthread eine Methode aufruft, die dann im Haupt-Thread abgearbeitet wird.
Wie mache ich das?

Viele Grüße,

Jens
 
Jens Hibbeler hat gesagt.:
Die Methode WaitForSingleObject(threadFertig, INFINITE) wartet zwar in Haupt-Thread, doch muss ich dann doch immer noch nachschauen, ob der Thread fertig ist. Auch das will ich vermeiden. Also am besten wäre es, wenn mir der Nebenthread eine Methode aufruft, die dann im Haupt-Thread abgearbeitet wird.

Das geht definitiv nicht.
Aber wieso machst du es nicht so:

Code:
#include <iostream>
#include <pthread.h>

using namespace std;

bool event = false;

class ThreadListener{
    public : virtual void eventHandler(void) = 0;
};

class MyThreadListener : public ThreadListener{
    void eventHandler(void){
        cout << "Jetzt trat ein event auf nun bearbeite den event" << endl;
    }
};

//wird in einem neuen Thread ausgeführt und horcht nach einem Event
void* threadFunction(void * listener){
        while(true){
                usleep(100);       //verzoegerung damit cpu nicht so belastet wird
                if(event == true){
                        ((ThreadListener*)listener)->eventHandler();  //Benachrichtige deinen Eventhandler
                        event = false;  //Setze das Ereigniss zurueck...
                }
        }
}

int main(){
    ThreadListener* tl = new MyThreadListener();

   pthread_t threads[1];
   pthread_create(&threads[0], NULL, threadFunction, tl);

    //Hier geht der Haupthread weiter und loest nach einer bestimmten zeit ein event aus
   while(true){
        sleep(5);
        event = true;
   }
   delete tl;
}

Gruß

RedWing
 
Zuletzt bearbeitet:
Noch ein Nachtrag:

In der Methode:

void eventHandler(void) kannst du dann dein synchrones Protokoll
benachrichtigen. Somit wird das synchrone Protokoll asynchron von
deinem Programm bedient da die Methode void eventHandler(void)
aus dem thread heraus aufgerufen wird.

Ich hoffe ich hab dich richtig verstanden und konnte dir helfen....

Gruß

RedWing
 
Hallo,

nocheinmal danke für Euren Rat und Tat :). Was ich gesucht hatte, war den Main-Thread über das Ende eines Nebenthreads zu benachrichitgen -ohne das der Main-Thread auf den Neben-Thread wartet. Ich habe das ganze jetzt mit Windows Events gelöst.

Beispiel:

Code:
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	switch (message) {
	case WM_THREADFINISHED:
        {
                //Hier den Code ausführen, wenn der Neben-Thread fertig ist.
                DestroyWindow(hWnd);
			break;
		}

	}
return DefWindowProc(hWnd, message, wParam, lParam);
}


ATOM MyRegisterClass(HINSTANCE hInstance)
{
        WNDCLASSEX wcex = {0};
	wcex.cbSize        = sizeof(WNDCLASSEX);
	wcex.style         = CS_HREDRAW | CS_VREDRAW;
	wcex.lpfnWndProc   = (WNDPROC)WndProc;
	wcex.hInstance     = hInstance;
	wcex.hCursor       = LoadCursor(NULL, IDC_ARROW);
	wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
       	wcex.lpszMenuName  = "IDC_RAHMEN";
	wcex.lpszClassName = CLASSNAME ;
	return RegisterClassEx(&wcex);
}

WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
{
        HINSTANCE hInstance= GetModuleHandle(NULL);
        MyRegisterClass(hInstance);
        hWndtemp = CreateWindow(CLASSNAME, "szTitle", WS_OVERLAPPEDWINDOW,
		CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);
}

Viele Grüße,

Jens
 
Zurück