Im Thread Paint ausführen
-
vergiss bitte einfach dass es sowas wie threads gibt. du machst so grundlegende dinge falsch, beschäftige dich erstmal damit ordentlich programmieren zu lernen. DANN sieh dir threads an wenns denn unbedingt sein muss.
-
1. du hast recht das ich mich mit threads noch nicht beschäftigt habe (ausser ein bisschen in Java)
Aber so wie ich das sehe ist mein problem auch nicht unbedingt der thread, ich habe vorhin auch schon ein bisschen anders rumprobiert (ohne Thread) und ich habe einfach ein problem, weil ich nicht weiß, wie ich zB aus WM_TIMER WM_PAINT aufrufe
und soweit ich weiß brauche ich ja PostMessage() oder SendMessage() und die Funktion will wieder den handle meines Fensters, da würde ich sagen das es hwnd ist aber das funktioniert wieder nicht...Genauso weiß ich auch nicht wie ich den handle ausserhalb der WndProc Funktion und der Winapi Funktion bekomme, bei HWND hwnd; bekomme ich den handle des gesamten desktops, aber ich will ja nur den meines programms
also ich habe quasi ein Problem und suche eine Lösung bzw. Hilfe, ich habe auch schon 2 Bücher gewälzt und mir die finger warm gegoogelt und das ohne ERFOLG
aber sry wenn ich versucht habe in einem forum hilfe zu finden, ich habe einfach gedacht, dasd ich einen kleinen fehler habe, ein hilfbereiter kommt, eben eine funktion einsetzt die ich übersehen hatte und dann alles läuft...
-
Du kannst z.B. bei _beginthread() das gültige hWnd mit übergeben und bei deiner Thread-Funktion aus pvoid wieder rausfischen.
Bisher deklarierst du da zwar ein hwnd, aber initialisiert es nirgends

-
klar ich kann es ja übergeben, gar nicht dran gedacht
tausend dank, es läuft jetzt genau so wie ich es wollte...
aber echt genau so einen denkanstoss habe ich gesucht

danke nochmal geeky...
@hustbaer so einen denkanstoss hättest du mir doch auch geben können, dann wäre es viel einfacher gewesen
danke auch an die anderen

-
Ehrlich gesagt hab' ich den Window Handle Patzer übersehen, und bin dann auf dumme Ideen gekommen.
Es geht natürlich in einem anderen Thread Funktionen wie InvalidateRect etc. aufzurufen, es ist nur trotzdem meistens keine gute Idee.Dein Programm hat z.B. einen "Schönheitsfehler" (milde gesagt), nämlich beendest du den "Ball Thread" niemals. Da du aus dem "Ball Thread" aber auf dein Fenster zugreifst ... solltest du ihn beenden bevor du das Fenster schliesst. Würdest du diesen "Schönheitsfehler" beheben wollen sähe die "naive" Variante wahrsheinlich etwa so aus:
HANDLE g_endBallThreadEvent = 0; HANDLE g_ballThread = 0; //... int WINAPI WinMain (HINSTANCE hThisInstance, HINSTANCE hPrevInstance, LPSTR lpszArgument, int nFunsterStil) { // ... g_endBallThreadEvent = CreateEvent(0, true, 0, 0); // ... // message loop hier // ... // cleanup: CloseHandle(g_endBallThreadEvent); CloseHandle(g_ballThread); // ... } LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { // ... //_beginthread(Thread,0,NULL); g_ballThread = (HANDLE) _beginthreadex(...); // ... case WM_DESTROY: // zuerst thread beenden, dann erst fenster schliessen: SetEvent(g_endBallThreadEvent); WaitForSingleObject(g_ballThread, INFINITE); // ... } unsigned Thread(PVOID pvoid) { // ... while (WaitForSingleObject(g_endBallThreadEvent, 0) != WAIT_OBJECT_0) { // ... InvalidateRect(hwnd, ...); } }Sieht noch halbwegs einfach aus. Was man aber auf den ersten Blick nicht unbedingt sieht: wenn der "Ball Thread" gerade dabei ist InvalidateRect aufzurufen, während der Hauptthread in "WaitForSingleObject(g_ballThread, INFINITE);" wartet ... wird das Progamm "feststecken", und du hast einen Deadlock gebaut.
Warum? InvalidateRect "sendet" die Message an das Fenster. Da das Fenster zu diesem Zeitpunkt noch existiert versucht das Betriebssystem eben die Message zu "senden", und "senden" bedeutet dass darauf gewartet wird dass die Message vom Hauptthread (dem das Fenster gehört) verarbeitet wurde. Der Hauptthread wartet allerdings gerade in "WaitForSingleObject", und in "WaitForSingleObject" verarbeitet er eben keine Messages, auch nicht welche die "gesendet" werden. Ergo wartet der "Ball Thread" darauf dass der Hauptthread seine Message verarbeitet, und der Hauptthread darauf dass sich der "Ball Thread" beendet. Der "Hauptthread" verarbeitet allerdings keine Messages mehr bevor der "Ball Thread" sich nicht beendet hat, und der "Ball Thread" beendet sich nicht bevor der "Hauptthread" nicht seine Message verarbeitet hat. Ein klassischer Deadlock.
Natürlich gibt es Möglichkeiten das zu fixen, aber dadurch wird alles bloss noch viel komplizierter.
Glaubst du mir jetzt dass Threads die Hölle sind (zumindest wenn man korrekte Programme schreiben will, die u.a. auch immer so funktionieren wie sie sollten)?
-
@hustbaer:
InvalidateRect versendet keine Nachricht und kann auch von eionem fremden Thread ohne Gefahr aufgerufen werden! Anders UpdateWindow/RedrawWindow!
-
Ok, in dem Fall würde InvalidateRect noch gehen aber der Aufruf von UpdateWindow (der im Source Code des OP ja auch enthalten ist) würde den Deadlock komplett machen.
Worauf ich eigentlich hinaus wollte: mehrere Threads + Fenster = schwierig. Gewisse Dinge wie PostMessage kann man eigentlich immer gefahrlos machen, bei anderen Funktionen wird's schnell kompliziert.
p.S.: sorry für den faktischen Fehler

-
ok, kein problem
danke für den code ich werd ihn mir nachher mal in ruhe anschauen...

PS: ich bin momentan dabei sound und punkte einzubauen und die Optik des Spiels zu verbessern, wahrscheinlich treffe ich bald wieder auf probleme, dann meld ich mich nochmal...

-
@hustbaer: Leider geht das aus den API Funktionen oft nicht hervor, dass Windows Nachrichten durch sie erzeugt werden. Dadurch kann man sich hier schon leicht vertun.
-
Martin Richter schrieb:
@hustbaer: Leider geht das aus den API Funktionen oft nicht hervor, dass Windows Nachrichten durch sie erzeugt werden. Dadurch kann man sich hier schon leicht vertun.
Genau deswegen hab' ich ja vermutet dass InvalidateRect eine Message senden würde - weil so viele andere Fenster-Manipulations-Funktionen es machen ohne dass es explizit irgendwo stehen würde.