Registriert: Mi Nov 30, 2011 21:41 Beiträge: 136 Wohnort: Bad Vilbel
Programmiersprache: Delphi 7
Hallo allerseits, Ich bin immoment irgendwie total am verzweifeln mit Multithreading. Hab mir das Tutorial von Lossy ex und was ich sonst noch so im Internet finden konnte durchgelesen, aber mir hat bisher nix weiterhelfen können
Ich will eigentlich nicht mehr machen als an einer Stelle 2 Threads gleichzeitig laufen zu lassen. Meine Idee war folgende: -VCL Thread kommt an eine gewisse Stelle -VCL Thread startet einen weiteren Thread. -VCL Thread und weiterer Thread berechnen das nötige. -VCL Thread soll warten bis anderer Thread fertig ist. -VCL Thread soll fortfahren. [...] -VCL Thread zeichnet via OpenGL alles [...] -VCL Frameende.
Über OnIdle sollen diese Schritte dann wiederholt. Meine Codeumsetzung hat stark variiert, daher hier mein momentaner Code-Zustand:
Code:
constructor TDCMatch.Create();
begin
inherited Create;
Player := TDCPlayer.Create(meSetByteColor(16,16,255,255));
TheMatch.PlayerZeroCollision();// Aufwendige Funktion (TheMatch ist die einzige Instanz von TDCMatch)
sFinish();// Soll zeigen das er fertig ist.
end;
end;
end;
Habe das Spiel schon ohne Multithreading schon erfolgreich ausgeführt, liegt also nicht an Fehlern in den Funktionen.
Noch eine zusätzliche Frage, weswegen das wahrscheinlich auch nicht funktioniert: Wenn ein Thread am Ende von Execute ankommt, startet er dann von vorne, ist er terminated oder was passiert dann genau?
Registriert: Sa Aug 18, 2007 18:47 Beiträge: 694 Wohnort: Köln
Programmiersprache: Java
Ist zwar jetzt nicht die Lösung deines Problems, aber eigentlich brauchst du für dieses Problem gar kein Multithreading, wenn der VCL Thread sowieso auf den anderen Thread wartet bis dieser fertig ist. Dann kann die Arbeit auch im VCL Thread gemacht werden.
Zitat:
-VCL Thread soll warten bis anderer Thread fertig ist.
_________________ Es werde Licht. glEnable(GL_LIGHTING); Und es ward Licht.
Zitat aus einem Java Buch: "C makes it easy to shoot yourself in the foot; C++ makes it harder, but when you do it blows your whole leg off"
Registriert: Sa Jan 01, 2005 17:11 Beiträge: 2067
Programmiersprache: C++
Knittel hat geschrieben:
Noch eine zusätzliche Frage, weswegen das wahrscheinlich auch nicht funktioniert: Wenn ein Thread am Ende von Execute ankommt, startet er dann von vorne, ist er terminated oder was passiert dann genau?
Der Thread ist terminated, da du noch das Flag für die automatische Freigabe gesetzt hast, wird auch automatisch sein Speicher freigegeben. Das ist daher also nur zu empfehlen, wenn der Thread selber keine Daten speichert sondern sie (synchronisiert) woanders speichert.
Registriert: Mi Nov 30, 2011 21:41 Beiträge: 136 Wohnort: Bad Vilbel
Programmiersprache: Delphi 7
Erstmal danke für die ganzen Antworten, aber ich bin mir immernoch nicht ganz sicher, wie die Lösung jetzt aussehen soll.
Zitat:
Ist zwar jetzt nicht die Lösung deines Problems, aber eigentlich brauchst du für dieses Problem gar kein Multithreading, wenn der VCL Thread sowieso auf den anderen Thread wartet bis dieser fertig ist. Dann kann die Arbeit auch im VCL Thread gemacht werden.
Es kommt ja zwischen VCL-Thread startet den anderen Thread und VCL-Thread wartet auf den anderen Thread noch eine aufwendige Berechnungen, bzw. In meiner Anwendung gibt es 2 aufwendige Prozeduren. Der VCL-Thread startet den 2ten Thread. VCL-Thread arbeitet eine Prozedur ab der andere Thread die andere Prozedur. Da mit den Ergebnissen der Prozeduren danach weitergerechnet werden soll, soll hier der VCL-Thread (wenn nötig) auf Thread 2 warten.
Zitat:
Dort wo du in deinem Code Multithreadnig starten willst deklarierst du einfach eine Variable und rufst den Konstruktor auf:
das heißt, ich muss in jedem Frame den Thread neu erstellen? Und dann jedes mal mit FreeOnTerminate = true?
Zitat:
Der Thread ist terminated, da du noch das Flag für die automatische Freigabe gesetzt hast, wird auch automatisch sein Speicher freigegeben. Das ist daher also nur zu empfehlen, wenn der Thread selber keine Daten speichert sondern sie (synchronisiert) woanders speichert.
OK. Das hilft mir auch schonmal gut weiter Ich probier noch ein wenig rum, würde mich aber noch über weitere Ratschläge freuen.
EDIT: OK. Habs jetzt in einer "Sonderform" zum laufen gebracht.
Immoment, das ist mir klar, werden die Berechnungen nacheinander ausgeführt, habe ich allerdings testweise mal eingebaut um zu schauen wo das Problem liegt. Sobald ich PlayerOneCollision(); vor dem warten auf den 2ten Thread einfüge, gibt es einen Deadlock (spätestens nach 1 sekunde). Ist da vielleicht noch ein Problem mit der Critical Section? Ich dachte, der 2te Thread kann rein, sboald ihn der erste verlassen hat (er ist sozusagen in der Warteschlange), oder irre ich mich da wieder?
Sicherheitshalber nochmal der Code der in den beiden Threads ausgeführt wird. 1. Überprüft Kollision von Spieler 1en mit Computer 0en 2. Überprüft Kollision von Spieler 0en mit Computer 1en Da ja somit komplett auf unterschiedliche Objekte zugegriffen wird, dachte ich, dass man diese Aufgaben parallell ausführen kann.
Registriert: Do Sep 02, 2004 19:42 Beiträge: 4158
Programmiersprache: FreePascal, C++
Ganz allgemein würde ich dir empfehlen, dir mal das Konzept von Semaphoren zu gemüte zu führen. Das würde dir das Erzeugen/Löschen sparen und du kannst dem Thread einfach ein Startsignal geben, wenn's so weit ist. Ebenso kann der Thread so sauber zurückgeben, dass er fertig ist.
Ansonsten erscheint mir das Konzept sinnig, so ähnlich mache ich es mit ManiacLab ja auch. Woran erkennst du den Deadlock, wenn er auftritt? Kannst du mal im Debugger nachschauen, wo die Threads dann warten?
grüße
ps.: Solltest du wider Erwarten unter Linux unterwegs sein ist helgrind das Mittel der Wahl, um des Problem zu untersuchen.
_________________ If you find any deadlinks, please send me a notification – Wenn du tote Links findest, sende mir eine Benachrichtigung. current projects: ManiacLab; aioxmpp zombofant network • my photostream „Writing code is like writing poetry“ - source unknown
„Give a man a fish, and you feed him for a day. Teach a man to fish and you feed him for a lifetime. “ ~ A Chinese Proverb
Das Problem war, dass ich die Variable mtThreadCount erst gesetzt habe, nachdem ich den anderen Thread erzeugt habe (hier sogar noch nach PlayerOneCollision) und somit der Thread manchmal fertig war bevor mtThreadCount = 1 gesetzt wurde. Da der Thread danach fertig war blieb mtThreadCount die ganze Zeit 1 und die Anwendung blieb stehen.
Wieso benutzt du nicht einfach TThread.WaitFor? FreeOnTerminate muss dann allerdings false sein, sonst würde man u.U. auf eine nicht mehr existierende Instanz zugreifen. Außerdem muss man die Instanz danach dann natürlich auch selbst freigeben.
Registriert: Mi Nov 30, 2011 21:41 Beiträge: 136 Wohnort: Bad Vilbel
Programmiersprache: Delphi 7
WaitFor hatte bei mir irgendwie nicht richtig funktioniert (vermutlich weil ich es falsch angewandt habe), aber ich hab sowieso vor, das nochmal zu überarbeiten, bzw. ne eigene Threadklasse drüber zu schreiben um die ganze Angelegenheit ein wenig zu vereinfachen.
Mitglieder in diesem Forum: Majestic-12 [Bot] und 6 Gäste
Du darfst keine neuen Themen in diesem Forum erstellen. Du darfst keine Antworten zu Themen in diesem Forum erstellen. Du darfst deine Beiträge in diesem Forum nicht ändern. Du darfst deine Beiträge in diesem Forum nicht löschen. Du darfst keine Dateianhänge in diesem Forum erstellen.