Parameter & Thread

Programmiersprachen, APIs, Bibliotheken, Open Source Engines, Debugging, Quellcode Fehler und alles was mit praktischer Programmierung zu tun hat.
Antworten
Neo.uc
Beiträge: 19
Registriert: 17.04.2003, 16:31
Kontaktdaten:

Parameter & Thread

Beitrag von Neo.uc »

CHallo, ich will gleich zur Sache kommen:

Ich habe eine Anwendung, welche ein einfaches Windows Fenster erzeugt.
Danach starte ich einen Thread und übergebe diesem als Parameter das Fenster-Handle.

Soweit funktioniert auch alles ganz gut, das übergebene Fenster-Handle hat innerhalb des Threads den richtigen Wert.

Hier ein bisschen Code zur besseren Verständnis:

Code: Alles auswählen

void CWndThread::Execute(void *Parameter)
{
	HWND *hWnd = (HWND*)Parameter;
	MSG	msg;

	while(true)
	{
		while (GetMessage(&msg, *hWnd , 0, 0)) 
		{
			TranslateMessage(&msg);
			DispatchMessage(&msg);
		}
	}
}
Jetzt taucht allerdings ein seltsames Phänomen auf:
Manchmal lässt es sich Ausführen (Release & Debug) und dann wieder nicht.
Wenn es mal nicht funktioniert meldet sich der Debugger mit einer Zugriffsverletzung.

Meine erste Idee war daraufhin das Fenster-Handle nicht zu übergeben und folgendermaßen bekannt zu machen:

Code: Alles auswählen

extern HWND g_hWnd;
im Code dann geändert auf:

Code: Alles auswählen

void CWndThread::Execute(void *Parameter)
{
	MSG	msg;

	while(true)
	{
		while (GetMessage(&msg, g_hWnd , 0, 0)) 
		{
			TranslateMessage(&msg);
			DispatchMessage(&msg);
		}
	}
}
Diese Variante funktioniert immer einwandfrei.


Kann mir eventuel jemand das Verhalten erklären bzw einen Tip geben wie ich es über die Parameterübergabe hinbekommen könnte ?

Danke
Zuletzt geändert von Neo.uc am 02.09.2010, 20:31, insgesamt 2-mal geändert.
Neo.uc
Beiträge: 19
Registriert: 17.04.2003, 16:31
Kontaktdaten:

Re: Verwendung eines "fremden" HWND in einem Thread

Beitrag von Neo.uc »

Ok, ich habe doch eine Lösung gefunden die Funktioniert.

Für alle die eines Tages mal das selbe Problem haben sollten:

Der Funktion:

Code: Alles auswählen

Funktionsaufruf des Threads(void *p)
Die Addresse des HWND übergeben

Code: Alles auswählen

HWND Parameter;
Funktion(&Parameter);
um anschließend mit

Code: Alles auswählen

HWND h = (HWND)&Parameter;
es aus dem Parameter rauszuholen.

Eigentlich Kinderleicht und Simpel, das hat man davon wenn man seit ettlichen Jahren keine Zeit mehr fürs Programmieren hatte ^^

Code: Alles auswählen

if(this->OutOfMemory())
delete Topic;
Benutzeravatar
Biolunar
Establishment
Beiträge: 154
Registriert: 27.06.2005, 17:42
Alter Benutzername: dLoB

Re: Verwendung eines "fremden" HWND in einem Thread

Beitrag von Biolunar »

Neo.uc hat geschrieben:

Code: Alles auswählen

Funktionsaufruf des Threads(void *p)
Die Addresse des HWND übergeben

Code: Alles auswählen

HWND Parameter;
Funktion(&Parameter);
um anschließend mit

Code: Alles auswählen

HWND h = (HWND)&Parameter;
es aus dem Parameter rauszuholen.
Das sieht falsch aus! Beschäftige dich am besten mal wieder mit Zeigern, die Grundlagen scheinen dir nicht mehr zu sitzen.
Guck:

Code: Alles auswählen

void foo(void* p)
{
    HWND handle = static_cast<HWND>(p);
}


void bar()
{
    HWND handle = xyz;
    foo(handle);
}
Benutzeravatar
CodingCat
Establishment
Beiträge: 1857
Registriert: 02.03.2009, 21:25
Wohnort: Student @ KIT
Kontaktdaten:

Re: Paramter & Thread [gelöst]

Beitrag von CodingCat »

Richtig, das geht ganz ohne Zeigermagie, weil sich HWND direkt als Zeiger interpretieren lässt.

Wäre das nicht der Fall, müsste man den Umweg über Zeiger gehen, und du müsstest deinen Code zum Holen des Parameters auf jeden Fall korrigieren:

Code: Alles auswählen

HWND h = *reinterpret_cast<HWND*>(Parameter);
statt "HWND h = (HWND)&Parameter;". Das ist aber bei Threads eine ganz heikle Angelegenheit, weil du einen Zeiger auf eine lokale Variable übergeben würdest, die zum Zeitpunkt der Thread Execution bereits zerstört sein könnte. Insofern hätte diese Lösung dann immer noch undefiniertes Verhalten.

Glücklicherweise geht es in diesem Fall ohne solche Fallstricke, wie Biolunar gezeigt hat.
alphanew.net (last updated 2011-07-02) | auf Twitter | Source Code: breeze 2 | lean C++ library | D3D Effects Lite
Neo.uc
Beiträge: 19
Registriert: 17.04.2003, 16:31
Kontaktdaten:

Re: Paramter & Thread [gelöst]

Beitrag von Neo.uc »

Ihr habt vollkommen recht.

Es läuft zwar aber was mir jetzt erst auffällt ist dass die CPU Auslastung auf max läuft da aus irgendeinem Grund
etwas in das HWND reinpfuscht.

Danke für die Hinweise ich versuch das jetzt mal umzusetzen und gebe dann Rückmeldung ob es klappt :)
Neo.uc
Beiträge: 19
Registriert: 17.04.2003, 16:31
Kontaktdaten:

Re: Paramter & Thread [gelöst]

Beitrag von Neo.uc »

Also mit

Code: Alles auswählen

void foo(void* p)
{
HWND handle = static_cast<HWND>(p);
}


void bar()
{
HWND handle = xyz;
foo(handle);
}
funktioniert das übergeben des HWND Prima.

Bleibt nur noch das Problem dass die MsgLoop mit GetMessage innerhalb des Threads ihre Arbeit nicht macht.
Sie wird zwar aufgerufen aber das Fenster bleibt "tot" (es ist sichtbar reagiert aber auf nichts).
Die Callback Funktion ist ok, denn wenn ich die MsgLoop aus dem Thread heraus nehme funktioniert alles wie es soll,
allerdings hängt dann die eigentliche Anwendung in der MsgLoop dieses Fensters fest.

Auf PeekMessage verzichte ich mit Absicht, da diese in einer Schleife laufen muss welche CPU Zeit frisst.
Ich kann auch kein Sleep(x) in solch eine Schleife einsetzen, da es in 100% Echtzeit laufen muss.

Jemand eine Idee woran das liegen könnte ?
Neo.uc
Beiträge: 19
Registriert: 17.04.2003, 16:31
Kontaktdaten:

Re: Paramter & Thread [gelöst]

Beitrag von Neo.uc »

Hier ein kleines Schema über den Aufbau , eventuell wirds dann ja verständlich:

Bild

Geplant ist, dass die DLL ein Unsichtbares Fenster hat, welches über eine MSG-CALLBACK Funktion verfügt.
Über Spy++ hab ich heruasgefunden, dass ein Handle auf das Fenster existiert, aber keine Fensterprozedur.
Daraus schlau werde ich allerdings nicht :?

Edit:
Ich habe folgendes über google gefunden:

Code: Alles auswählen

GetMessage liest nur die Nachrichten, für Fenster dieses Threads. Dein Thread erzeugt aber keine Fenster, also kann auch keine Nachricht ankommen...
Fenster werden im Kontext eines Threads erzeugt. Entsprechend bekommt die Nachrichtenschleife dieses Threads auch die Meldungen für dieses Fenster.
Du kannst in einem Thread keine Nachrichten für ein Fenster aus einem anderen Thread empfangen oder abarbeiten. 
Stimmt es dass es hierfür keine Lösung gibt ? Hört sich nach genau meinem Problem an
Helmut
Establishment
Beiträge: 237
Registriert: 11.07.2002, 15:49
Wohnort: Bonn
Kontaktdaten:

Re: Paramter & Thread

Beitrag von Helmut »

Du kannst das Fenster direkt im Thread erstellen. Anders geht es nicht von einer DLL aus, ohne das die Exe das beachtet (also eine MessageLoop bereitstellt)

Ciao
Neo.uc
Beiträge: 19
Registriert: 17.04.2003, 16:31
Kontaktdaten:

Re: Paramter & Thread

Beitrag von Neo.uc »

Angenommen ich erstelle das Fenster im Thread.
Dann ist ja aus der Sicht dieses Threads der eigentliche DLL Process ja auch ein fremder Thread.
Unglücklicherweiße muss ich später vom Thread aus auf den Thread der DLL zugreifen und ebenso Nachrichten an
die eigentliche Anwendung schicken.

Irgendwie bricht gerade mein ganzes Konzept zusammen.
Zugegebenermaßen ist es sicherlich unschön für eine GetMessage Funktion mit Threads und deren Problemen zu arbeiten,
Ich werd mir heute nacht im Schlaf mal lieber ein neues Konzept ausdenken ^^

Trotzdem Danke an alle die sich die Zeit genommen haben das hieralles zu lesen und mir zu helfen :)
Antworten