Announcement

Collapse
No announcement yet.

Warum keine Ausgabe in InfoBox?

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • Warum keine Ausgabe in InfoBox?

    Hallo,
    kleine Geschichte vorweg: Ich plane ein Browserspiel in kleinem Rahmen.
    Dafür programmiere ich gerade in c# ein Tool, welches mir die Auswertung von vielen Daten dieses Spieles auf einmal erlaubt, um zu sehen, ob es
    einigermaßen gebalanced ist. Es geht darum, dass zwei Kämpfer einen Kampf ausfechten.

    Mein C# Programm ist mit einer TextBox ausgestattet, in dem der Kampfbericht erscheint. In der ersten Version gab es zudem nach jedem Kampf eine Statistik, wie die Kämpfer abgeschnitten haben. Logischerweise war dies aber recht nervig (da mit MessageBox), wenn man 100+ Kämpfe hintereinander weg simulieren ließ.
    Also änderte ich das so, dass diese Statistik nur noch nach dem letzten Kampf angezeigt wird.

    Doch jetzt herrscht totale Funkstille in der TextBox, bis nach dem letzten Kampf und dann werden alle Kämpfe auf einmal in die Box gequetscht. Wäre normal nicht weiter schlimm, nur dauert das extrem lang bei dreistelligen Kampfzahlen oder hängt sich bisweilen auch mal auf. In der Clickvariante nach jedem Kampf war das kein Problem.
    Ich frage mich jetzt, was ich ändern muss, damit nach jedem Kampf auch eine Anzeige in der Textbox erscheint, um verfolgen zu können, wie weit der Rechner denn schon ist.

    Hier mal mein Code dazu:
    (Es gibt eine Hauptform, dazu die Klasse Kampf und die Klasse Klon(=Kämpfer))

    [highlight=c#]

    //durch diesen Button wird die Kampfsimulation gestartet.
    //vorher wurden die Kämpfer erstellt, die gegeneinander antreten sollen
    private void buttonStartFight_Click(object sender, EventArgs e)
    {
    //Infofeld leeren
    infoFeld.Text = "";
    buttonStartFight.Enabled = false;

    kampfStart();
    }
    [/highlight]

    [highlight=c#]

    //hier wird der eigentliche kampf dann gestartet
    private void kampfStart()
    {
    Kampf kampf = new Kampf(klon[0], klon[1]);
    //die Methode battle aus der Klasse kampf ist public und hat string als Rückgabewert
    infoFeld.Text += Environment.NewLine + kampf.battle();
    infoFeld.Text += Environment.NewLine + (kaempfegemacht + 1) + ". Kampf abgeschlossen ...";
    kaempfegemacht++;

    if (kaempfegemacht < kampfAnzahl)
    {
    kampfStart();
    }
    else
    {
    kampf.statistikAusgabe();
    }
    }
    [/highlight]

    Aus meiner Sicht müsste die Infobox mit dem Text gefüllt werden, der durch die Methode battle erstellt wird. Unabhängig davon, wie oft sich die Methode kampfStart() noch aufruft? Tut sie aber nicht ... wo ist denn da mein Denkfehler?

  • #2
    Also ich würde jetzt in .Net z.B. darauf verzichten Rekursion zu verwenden und eine Schleife drum herum machen. Schleifen sind stabiler (du kannst keinen Stack Overflow erzeugen) und machen dasselbe. Eigentlich sollte das funktionieren. Hast Du Dich schon mal durch debugged? Tritt das Problem dann auch auf?

    Comment


    • #3
      Dein Code läuft endlos bis der letzte rekursive Aufruf von kampfStart ausgeführt ist. Erst dann bekommt Windows wieder zum Zug um auch mal das Zeichnen der infoBox auszuführen. Während das läuft sollte dir auch aufgefallen sein das deine Form nicht bedienbar ist. Die ~billige~ Lösung wäre in kampfStart mal Application.DoEvents() aufzurufen (vor dem rekursiven Aufruf von kampfStart). Richtig wäre es den Code in einen Thread auszulagern damit der Hauptthread das Zeichnen der Form übernehmen kann und du in deinem eigenen Thread den Kampf ausführen kannst.

      Comment


      • #4
        ah, thx für die tips.
        mit einer schleife hatte ich es zuerst, aber da gabs dasselbe problem.
        an einen eigenen thread hatte ich noch gar nicht gedacht. werde ich morgen mal testen
        gute nacht

        Comment


        • #5
          mit thread ging es auch nicht, da threads wohl keine rückgabe erlauben. ich hab das dann jetzt so gemacht:

          [highlight=c#]
          private void kampfStart()
          {
          Kampf kampf = new Kampf(klon[0], klon[1]);
          Task<string> simulation = Task<string>.Factory.StartNew(() =>kampf.battle());
          string ergebnis = "";
          ergebnis += simulation.Result;
          infoFeld.Text = (kaempfegemacht + 1) + ". Kampf abgeschlossen ...";
          ergebnis += Environment.NewLine + (kaempfegemacht + 1) + ". Kampf abgeschlossen ..." +
          Environment.NewLine;
          kaempfegemacht++;

          if (kaempfegemacht < kampfAnzahl)
          {
          kampfStart();
          }
          else
          {
          infoFeld.Text = ergebnis;
          kampf.statistikAusgabe();
          }
          }
          [/highlight]

          Comment


          • #6
            Ein Task ist ein Thread. Und mit Task.Result hast du den aktuellen Thread angehalten bis der Thread den du über den Task gestartet hast fertig ist. Das ist ein ziemlich überflüssiger Thread.
            Funktioniert das was du machst den? Also wird dein UI zwischenzeitlich aktualisiert? Das wäre ein Nebeneffekt den ich gerade nicht erwarten würden.


            Warum sollte der Thread was zurückgeben? Die gesamte kampfStart Logik sollte in einem nebenläufigen Thread ausgelagert werden. Und dieser Thread sollte dan zwischendurch dem Haputthread bescheid sagen wenn es was in der UI zu aktualisieren gibt.

            Comment


            • #7
              es hatte funktioniert, ich hab es aber dennoch nochmal geändert. Jetzt schaut es so aus:

              [highlight=c#]
              private void buttonStartFight_Click(object sender, EventArgs e)
              {
              infoFeld.Text = "";
              buttonStartFight.Enabled = false;

              //Skills für die Klone machen
              for (int i = 0; i < 2; i++)
              {
              Skills skillbauer = new Skills(klon[i]);
              skillbauer.ShowDialog();
              }
              Task simulation = Task.Factory.StartNew(() => kampfStart());
              }

              private void kampfStart()
              {
              string ergebnis = "";
              for (int i = 0; i < kampfAnzahl; i++)
              {
              Kampf kampf = new Kampf(klon[0], klon[1]);
              ergebnis += kampf.battle() + Environment.NewLine;
              infoFeld.Text = (i + 1) + ". Kampf abgeschlossen ...";
              ergebnis += Environment.NewLine + (i + 1) + ". Kampf abgeschlossen ..." +
              Environment.NewLine;

              if (i == (kampfAnzahl-1))
              {
              infoFeld.Text = ergebnis;
              kampf.statistikAusgabe();
              }
              }
              }
              [/highlight]

              Comment

              Working...
              X