Hallo, nachdem ich nun 3D Animationen und die Physik in meiner Engine fertig gestellt habe, würde ich mich gerne um den nächsten Schritt kümmern. Hierbei geht es um Multithreading. Ich habe mich dazu etwas in diverse Literatur eingelesen und das ganze so verstanden, dass ich einen Thread für das Updaten und einen Thread für das Rendern benötige. Diese werden dann am ende Synchronisiert. Nun gibt es ja mehrere Möglichkeiten um Threads in C# zu Synchronisieren. Zum einem gibt es die Möglichkeit mit Join(), was meiner Meinung nach nicht wirklich viel Sinn macht in einer Game Engine, da beide Threads nacheinander ausgeführt werden, was im Endeffekt keine Auswirkung auf die Performance hätte.
Aus diesem Grund habe ich mich für
beste Grüße
Andy
Aus diesem Grund habe ich mich für
AutoResetEvent
entschieden, welche ich für alle Threads nutze und im Main Thread dann warte bis diese gesetzt wurden um das neue Frame zu beginnen. Dies würde bedeuten beide Threads werden unabhängig parallel zueinander ausgeführt. Es bedeutet aber auch, dass der Scene Tree mit den Entitys erst nach dem die Threads synchronisiert wurden manipuliert werden darf. Sprich neue Entitys hinzufügen oder alte Entfernen. Ich habe hier mal ein kleines beispiel erstellt und würde gerne eurer Meinung dazu erfahren, ob man das ganze so machen könnte und wo es zu Problemen kommen könnte. C#-Quellcode
- using System;
- using System.Collections.Generic;
- using System.ComponentModel;
- using System.Data;
- using System.Drawing;
- using System.Linq;
- using System.Text;
- using System.Threading;
- using System.Threading.Tasks;
- using System.Windows.Forms;
- namespace MTTest
- {
- public partial class Form1 : Form
- {
- AutoResetEvent updateThread = new AutoResetEvent(false);
- AutoResetEvent renderThread = new AutoResetEvent(false);
- //AutoResetEvent mainLoopEvent = new AutoResetEvent(false);
- public Form1()
- {
- InitializeComponent();
- }
- /// <summary>
- /// Starten der main loop
- /// </summary>
- /// <param name="sender"></param>
- /// <param name="e"></param>
- private void button1_Click(object sender, EventArgs e)
- {
- Thread thread = new Thread(new ThreadStart(MainLoop));
- thread.Start();
- }
- /// <summary>
- /// Simulieren des Frame rendern und updaten
- /// </summary>
- private void MainLoop()
- {
- int i = 0;
- while (i < 10)
- {
- Console.WriteLine("*******************************************");
- Console.WriteLine("New Frame");
- Console.WriteLine("*******************************************");
- DateTime start = DateTime.Now;
- Thread ut = new Thread(new ThreadStart(UpdateThread));
- Thread rt = new Thread(new ThreadStart(RenderThread));
- ut.Start();
- rt.Start();
- updateThread.WaitOne();
- renderThread.WaitOne();
- // Hier sind beide threads mit ihrer arbeit fertig
- // und es könnten manipulationen an den GameElements durchgeführt werden.
- // um diese für das nächste frame zu haben
- DateTime end = DateTime.Now;
- var span = end - start;
- Console.WriteLine(span.Milliseconds);
- i++;
- }
- }
- /// <summary>
- /// Updaten der Scene
- /// </summary>
- private void UpdateThread()
- {
- Console.WriteLine("Update Thread");
- for (int i = 0; i < 10; i++)
- {
- Console.WriteLine("Update " + i.ToString());
- }
- Thread.Sleep(30);
- Console.WriteLine("Update Done!");
- updateThread.Set();
- //renderThread.WaitOne();
- }
- /// <summary>
- /// Rendern der Scene
- /// </summary>
- private void RenderThread()
- {
- Console.WriteLine("Render Thread");
- for (int i = 0; i < 10; i++)
- {
- Console.WriteLine("Render " + i.ToString());
- }
- Thread.Sleep(10);
- Console.WriteLine("Render Done!");
- renderThread.Set();
- //updateThread.WaitOne();
- //mainLoopEvent.Set();
- }
- }
- }
beste Grüße
Andy