Laden...

Programm/GUI reagiert nicht mehr (Endlosschleife)

Erstellt von Lotus vor 12 Jahren Letzter Beitrag vor 12 Jahren 4.289 Views
Thema geschlossen
L
Lotus Themenstarter:in
73 Beiträge seit 2011
vor 12 Jahren
Programm/GUI reagiert nicht mehr (Endlosschleife)

Hallo liebe Community,

ich programmiere zur Zeit in C# (WPF) ein Kartenspiel.
Zum testen führe ich alle Aktionen über einen einzigen Button aus, dass klappt in den meisten Fällen auch ganz gut, aber ab und zu bleibt das Programm einfach hängen. Es wird nicht beendet, aber ich kann mir das Gui nicht mehr anzeigen lassen und im TaskManager steht "Reagiert nicht mehr"...

Es ist einfach schrecklich einen Fehler zu suchen, der nur ab und zu auftaucht und keine Fehlermeldung verursacht! Wisst ihr eventuell eine Möglichkeit wie ich den Fehler genauer identifizieren kann?

Ich hatte überlegt ob man das Problem mit Debuggen näher beleuchten könnte, aber rein theoretisch würde ja ne Exception geworfen werden, falls der Debugger den Fehler gesehen haette oder?

G
538 Beiträge seit 2008
vor 12 Jahren

Du könntest auch in genau dem Moment in dem es Auftritt den Debugger anhängen und schauen, ob du zufällig zum Beispiel in einer Endlosschliefe hängst, indem du das Programm nach dem "reagiert nicht" einfach anhälst ...

Der Vorteil der Klugheit liegt darin, dass man sich dumm stellen kann - umgekehrt ist das schon schwieriger (K. Tucholsky)
Das Problem mit Internet-Zitaten ist, dass sie oftmals zu unrecht als authentisch angenommen werden. (K. Adenauer)

L
Lotus Themenstarter:in
73 Beiträge seit 2011
vor 12 Jahren

Hey, genialer Tipp 😃

Ich habs mal ausprobiert und es hat glaube auch etwas gefunden, folgendes:

	this	Der Wert von "local" oder von Argument "<this>" ist in diesem Anweisungszeiger nicht verfügbar und kann daher nicht ermittelt werden. Möglicherweise wurde er bei der Optimierung entfernt.	PokerGuiTest.Card  

Der Code dazu ist:

        public Rank myRank
        { 
            get { return rank; } 
        }

Kann einer erklären was damit gemeint ist?

Edit:
Also wenn ich dann noch ein paar Schritte weiterklicke, dann komm ich irgendwann in eine Endlosschleife, aber warum er den Zähler auf Werte wie:
i 11906461 int
setzt, weiß ich nicht 😦

Edit2:
Irgendwann wird sogar einfach der Debugger beendet o.O
Außerdem schreint das Programm jedesmal an einer anderen Stelle zu halten

G
538 Beiträge seit 2008
vor 12 Jahren

Naja - er wird den Zähler auf diese Werte setzen, weil eventuell deine Abbruchbedingung falsch ist - wie sieht denn die fragliche schleife aus?

Diese Meldung mit der Optimierung ist im übrigen kein Fehler, sondern nur ein Hinweis auf genau das was da steht (nämlich, dass der Code den du siehst nicht zwingend das ist was der Compiler drauß gemacht hat).

Dass es jedes mal woanders hält ist klar, wenn es sich um eine Endlosschleife handeln sollte, denn wie willst du auf die gleiche Position kommen, wenn du keinen Breakpoint nutzt?

Ich würde mich auf die Schleife konzentrieren ...

Der Vorteil der Klugheit liegt darin, dass man sich dumm stellen kann - umgekehrt ist das schon schwieriger (K. Tucholsky)
Das Problem mit Internet-Zitaten ist, dass sie oftmals zu unrecht als authentisch angenommen werden. (K. Adenauer)

L
Lotus Themenstarter:in
73 Beiträge seit 2011
vor 12 Jahren

Die Schleife sieht so aus:

for (int i = nPlayer - 1; i > 0; i--)

nPlayer ist 2! (zeigt Debugger an!)
i ist aber wie oben schon erwähnt irgendwas in den höchsten Höhen!
Das er dann nicht abbricht ist mir schon klar, nur das Problem ist halt, dass mir der Debugger nicht anzeigt, warum i auf einmal so eine große Zahl ist.

G
538 Beiträge seit 2008
vor 12 Jahren

Leg mal nen Breakpoint auf die Schleife und schau dir genauer an was passiert

Der Vorteil der Klugheit liegt darin, dass man sich dumm stellen kann - umgekehrt ist das schon schwieriger (K. Tucholsky)
Das Problem mit Internet-Zitaten ist, dass sie oftmals zu unrecht als authentisch angenommen werden. (K. Adenauer)

L
Lotus Themenstarter:in
73 Beiträge seit 2011
vor 12 Jahren

Ich bin mir jetzt nicht sicher ob ich nen Fehler gemacht habe, aber jetzt lief das folgendermaßen ab:

Er ist zur Schleife gesprungen, ich bin 1 Step weitergegangen und hab i beobachtet, wenn das okay war, bin ich zur Rücksprungadresse gesprungen, dann wurde mir das Gui angezeigt und ich konnte erneut auf den Button klicken um das ganze laufen zu lassen...

Nach dem 4ten Mal, hat sich das allerdings irgendwie geändert:
Nachdem ich in die Schleife mit 1 Step reingesprungen bin, wurde auf einmal das Gui angezeigt und das Programm war festgehangen (im Debugger war nix mehr angezeigt), also habe ich das Programm angehalten und jetzt kam "Es ist keine Quelle verfügbar"...

Ist sowas schonmal bei dir aufgetreten?

Edit:
Tja das scheint auch nicht immer aufzutreten.. seltsam.
Ich verstehs einfach nicht, ich mach sonst NICHTS mit dem i, ich benutze lediglich den Wert für einen Indexzugriff auf eine Liste.. Das Problem ist halt, dass der Fehler auch manchmal schon beim ersten Mal auftaucht, manchmal aber auch erst ab 50x...
Weiterhin habe ich versucht, einfach mal folgende Abfrage einzubauen:

if(i > 10)
break;

Programm stürzt trotzdem ab 😕

6.862 Beiträge seit 2003
vor 12 Jahren

Hallo,

zeig mal mehr relevanten Code, aus den bisherigen Schnippseln kann man doch nichts ableiten.

Baka wa shinanakya naoranai.

Mein XING Profil.

L
Lotus Themenstarter:in
73 Beiträge seit 2011
vor 12 Jahren

Naja, das sind mehrere Klassen, ich bezweifle das man da mal schnell einsteigen wird, aber ich lad jetzt mal die Klasse hoch, in der jedesmal der Fehler auftritt:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;

namespace PokerGuiTest
{
    class CompareResults
    {
        List<Player> players = new List<Player>();

        public List<Player> myPlayerList
        {
            get { return players; }
            set { players = value; }
        }

//funktion zum erkennen welcher spieler gewinnt
        public Player winningPlayer()
        {
            int i = 0;
            int nPlayer = players.Count();
            Player actualWin = players.Last(); //player sind sortiert, letzter player hat 
//bestes blatt (mehrere können dasselbe blatt haben)
            Player player2;
            Result.CardCombination winningCombo = actualWin.myResult.myCombination;

            for (i = nPlayer - 1; i > 0; i--) //die schleife macht stunk
            {
                player2 = players.ElementAt(i - 1);
                if ((int)player2.myResult.myCombination < (int)actualWin.myResult.myCombination)
                    break;

                if ((int)actualWin.myResult.myCombination == (int)player2.myResult.myCombination)
                {
                    // straight flush vergleich oder flush oder straße oder high card
                    if (winningCombo == Result.CardCombination.STRAIGHTFLUSH
                        || winningCombo == Result.CardCombination.FLUSH 
                        || winningCombo == Result.CardCombination.STRAIGHT
                        || winningCombo == Result.CardCombination.HIGHCARD)
                    {
                        for (int j = 0; j < 6; i++) // HIER: das i++ war der Fehler
                        {
                            if ((int)player2.myResult.myCards[j].myRank > (int)actualWin.myResult.myCards[j].myRank)
                            {
                                actualWin = player2;
                                break;
                            }
                            else if ((int)actualWin.myResult.myCards[j].myRank > (int)player2.myResult.myCards[j].myRank)
                                break;
                            else if(j == 5 && (int)actualWin.myResult.myCards[j].myRank == (int)player2.myResult.myCards[j].myRank)
                                //return SPLITPOTT!!!!! 
                                return actualWin;//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
                                //return SPLITPOTT!!!!
                        }
               
                    }

                    //vierling vergleich + full house
                    else if (winningCombo == Result.CardCombination.FOURKIND || winningCombo == Result.CardCombination.FULLHOUSE)
                    {
                        if ((int)player2.myResult.myCards[0].myRank > (int)actualWin.myResult.myCards[0].myRank)
                            actualWin = player2;
                        else if ((int)player2.myResult.myCards[0].myRank == (int)actualWin.myResult.myCards[0].myRank) //wenn vierling gleich
                            if ((int)player2.myResult.myCards[1].myRank > (int)actualWin.myResult.myCards[1].myRank) // dann sidecard vergleich
                                actualWin = player2;
                            else if ((int)player2.myResult.myCards[1].myRank == (int)actualWin.myResult.myCards[1].myRank) // wenn sidecard gleich (bei vierling splittpot)
                                //return SPLITPOTT!!!!! 
                                return actualWin;//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
                                //return SPLITPOTT!!!!
                    }

                    //drilling vergleich + two pair
                    else if (winningCombo == Result.CardCombination.THREEKIND || winningCombo == Result.CardCombination.TWOPAIR)
                    {
                        if ((int)player2.myResult.myCards[0].myRank > (int)actualWin.myResult.myCards[0].myRank)
                            actualWin = player2;
                        else if ((int)player2.myResult.myCards[0].myRank == (int)actualWin.myResult.myCards[0].myRank) //wenn drilling gleich
                            if ((int)player2.myResult.myCards[1].myRank > (int)actualWin.myResult.myCards[1].myRank) // dann sidecard vergleich
                                actualWin = player2;
                            else if ((int)player2.myResult.myCards[1].myRank == (int)actualWin.myResult.myCards[1].myRank) //wenn sidecard1 gleich
                                if ((int)player2.myResult.myCards[2].myRank > (int)actualWin.myResult.myCards[2].myRank) // dann sidecard2 vergleich
                                    actualWin = player2;
                                else if ((int)player2.myResult.myCards[2].myRank == (int)actualWin.myResult.myCards[2].myRank)
                                    //return SPLITPOTT!!!!! 
                                    return actualWin;//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
                                    //return SPLITPOTT!!!!
                    }

                    //one piar
                    else if (winningCombo == Result.CardCombination.ONEPAIR)
                    {
                        if ((int)player2.myResult.myCards[0].myRank > (int)actualWin.myResult.myCards[0].myRank)
                            actualWin = player2;
                        else if ((int)player2.myResult.myCards[0].myRank == (int)actualWin.myResult.myCards[0].myRank) //wenn one pair gleich
                            if ((int)player2.myResult.myCards[1].myRank > (int)actualWin.myResult.myCards[1].myRank) // dann sidecard vergleich
                                actualWin = player2;
                            else if ((int)player2.myResult.myCards[1].myRank == (int)actualWin.myResult.myCards[1].myRank) //wenn sidecard1 gleich
                                if ((int)player2.myResult.myCards[2].myRank > (int)actualWin.myResult.myCards[2].myRank) // dann sidecard2 vergleich
                                    actualWin = player2;
                                else if ((int)player2.myResult.myCards[2].myRank == (int)actualWin.myResult.myCards[2].myRank) //wenn sidecard2 gleich
                                    if ((int)player2.myResult.myCards[3].myRank > (int)actualWin.myResult.myCards[3].myRank) // dann sidecard3 vergleich
                                        actualWin = player2;
                                else if ((int)player2.myResult.myCards[3].myRank == (int)actualWin.myResult.myCards[3].myRank)
                                    //return SPLITPOTT!!!!! 
                                    return actualWin;//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
                                    //return SPLITPOTT!!!!
                    }
                 }
    
            }

            return actualWin;
        }
    }
}

Edit:

Am besten noch die Klasse, die das Ganze aufruft:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;

namespace PokerGuiTest
{
    /// <summary>
    /// Interaktionslogik für Window1.xaml
    /// </summary>
    public partial class Window1 : Window
    {
        private List<System.Windows.Controls.Image> images = new List<System.Windows.Controls.Image>();
        private AnalyzeCards analyze = new AnalyzeCards();
        private List<Player> member = new List<Player>();
        private Player player = new Player();
        private KI ki = new KI();

        public Window1()
        {
            InitializeComponent();
            member.Add(player);
            member.Add(ki);
            initializeImageList();
        }

        private void initializeImageList()
        {
            images.Add(image5);
            images.Add(image6);
            images.Add(image7);
            images.Add(image8);
            images.Add(image9);
        }

        private void button1_Click(object sender, RoutedEventArgs e)
        {
            this.Close();
        }

        private void button1_Click_1(object sender, RoutedEventArgs e)
        {
                Deck deck = new Deck();
                BitmapImage bmp;
                Card card;
                string path = System.IO.Path.GetFullPath(@"cards/");

                foreach (Player pl in member)
                {
                    pl.eraseCards();
                    card = deck.deal();
                    bmp = new BitmapImage(new Uri(path + card.myPictureAdress, UriKind.Absolute));
                    pl.setCard(card);
                    if (pl.myID == 2)
                    {
                        image1.Source = bmp;
                        card = deck.deal();
                        bmp = new BitmapImage(new Uri(path + card.myPictureAdress, UriKind.Absolute));
                        image2.Source = bmp;
                    }
                    else
                    {
                        image3.Source = bmp;
                        card = deck.deal();
                        bmp = new BitmapImage(new Uri(path + card.myPictureAdress, UriKind.Absolute));
                        image4.Source = bmp;
                    }

                    pl.setCard(card);
                }


                foreach (System.Windows.Controls.Image im in images)
                {
                    card = deck.deal();
                    bmp = new BitmapImage(new Uri(path + card.myPictureAdress, UriKind.Absolute));
                    im.Source = bmp;
                    foreach (Player pla in member)
                    {
                        pla.setCard(card);
                        pla.sortCards();
                    }
                }

                label1.Content = "Player (ID:" + player.myID + ")";
                label2.Content = "KI (ID:" + ki.myID + ")";
                label4.Content = analyze.analyzeCards(player, player.myCards);
                label3.Content = analyze.analyzeCards(ki, ki.myCards);
                CompareResults cmpR = new CompareResults();
                member.Sort();
                cmpR.myPlayerList = member;
                label5.Content = cmpR.winningPlayer().myID.ToString();

            
        }
    }
}

6.862 Beiträge seit 2003
vor 12 Jahren

Hallo,

du machst ja alles im Eventhandler in der GUI. Klar das das Programm dann keine Reaktion meldet weil alles durch deine Analyse blockiert ist. Guck einfach mal in unsere FAQ [FAQ] Warum blockiert mein GUI?

Baka wa shinanakya naoranai.

Mein XING Profil.

L
Lotus Themenstarter:in
73 Beiträge seit 2011
vor 12 Jahren

Das verstehe ich gerade nicht so recht.
Wo benutz ich denn einen EventHandler?
Meinst du innerhalb des Button_Clicks?

Soll ich jetzt die Analyse in einem extra Thread starten oder wie ist das gemeint?
(Bin mit Threads und Events noch nicht vertraut)

Edit:
Rein theoretisch ist das Gui ja gar nicht das Problem, ich lande nur irgendwie in einer Endlosschleife und dann ist klar dass das Gui nicht mehr mitzieht.

Edit2:
So ich hab den Fehler gefunden..
Oh man, an sowas kann man echt lange grübeln..
Danke an alle die mir versucht haben zu helfen, den Fehler habe ich im Quellcode mit "HIER" markiert.

@Talla,
über eine Antwort von dir wäre ich trotzdem noch froh 😃

156 Beiträge seit 2010
vor 12 Jahren

Wo benutz ich denn einen EventHandler?
Meinst du innerhalb des Button_Clicks?

ja

Soll ich jetzt die Analyse in einem extra Thread starten oder wie ist das gemeint?

ja

(Bin mit Threads und Events noch nicht vertraut)

dann wäre das jetzt ein guter Zeitpunkt sich damit auseinander zu setzen

916 Beiträge seit 2008
vor 12 Jahren

Hallo mogel,

ich tippe mal darauf das auch folgendes passiert ist/kann. Deine schleife sieht wie folgt aus.


for (int i = nPlayer - 1; i > 0; i--)

Wann nun nPlayer mal eins ist, dann läuft die schleife von 0- 2 x Int32.MaxValue.

Again what learned...

G
538 Beiträge seit 2008
vor 12 Jahren

Mir sind 2(3) Dinge aufgefallen:

  1. ich würde, wenn du
int i;

nicht häufiger brauchst selbiges erst im Schleifenkopf deklarieren und initialisieren,

  1. das hier schaut falsch aus:
 for (int j = 0; j < 6; i++)

und
3) ich glaube "actual" heißt nicht, was du glaubst, dass es heißt ...

Der Vorteil der Klugheit liegt darin, dass man sich dumm stellen kann - umgekehrt ist das schon schwieriger (K. Tucholsky)
Das Problem mit Internet-Zitaten ist, dass sie oftmals zu unrecht als authentisch angenommen werden. (K. Adenauer)

Hinweis von herbivore vor 12 Jahren

Der Fehler wurde bereits gefunden (siehe weiter oben).

Alle Nachfragen zum Auslagern von langlaufenden Aktionen aus dem GUI in extra Threads sind überflüssig, weil alles ausführlich in der FAQ beschrieben ist.

Thema geschlossen