Problema al salir de función void en C#

Meta Seguir

Alfa
Usuario nuevo
¡Usuario con pocos negocios! ¡Utiliza siempre saldo de Forobeta!
Desde
6 Ago 2024
Mensajes
15
Buenas:

A veces entro en una función void, como que se llama así mismo y el programa no funciona como debería.

En la pila de llamadas muestra esto.
Pila-de-llamadas-01.jpg


Como puedes ver en la imagen en la Pila de llamadas, cada vez que intento salir del submenú, se repite cada vez más y en este caso hay tres, Volumen() y otras tres AjustesPrincipal(). Tiene que salir desde que salga, no que tenga comportamiento de este tipo.

Dejo código por si les dice algo en C# en modo consola.

Volumen();
Insertar CODE, HTML o PHP:
//     ** VOLUMEN ** 
//> Vol: ■■■■■■-- 6
//
//> ATRÁS    > INICIO

using LCD_Menu_con_submenus_Consola_03.Ventana01;
using System;

namespace LCD_Menu_con_submenus_Consola_03.Ventana03
{
    public class _0_Volumen
    {
        static int volumen = 6;
        public static void Volumen()
        {
            // Variables.
            string[] TEXTO =
            {
                "   ** VOLUMEN **    ", // Posición 0.
                " Vol: ",               // 1
                "■",                    // 2
                "-",                    // 3
                "ATRÁS",                // 4
                "INICIO",               // 5
                ">",                    // 6
                " "                     // 7
            };

            const int VOLMEN_MAX = 8;
            int opcion = 0; // 0 = Volumen, 1 = ATRÁS y 2 = INICIO.

            ConsoleKey teclaVolumen;

            // Limpiar pantalla.
            Console.Clear();

            // Mostrar menú.
            MostrarMenu();

            do
            {
                // ¿Están en la opción Volumen o 0?
                if (opcion == 0)
                {
                    // Sí. Mostrar volumen.
                    MostrarVolumen();
                }

                // Captura tecla y lo guarda en la variable teclaVolumen.
                teclaVolumen = Console.ReadKey(true).Key;

                // ¿Están en la opción Volumen o 0?
                
                if (opcion == 0)
                {
                    // Sí. Controlar el volumen.
                    if ((teclaVolumen == ConsoleKey.RightArrow) && (volumen < VOLMEN_MAX))
                    {
                        volumen++;
                    }
                    else if ((teclaVolumen == ConsoleKey.LeftArrow) && (volumen > 0))
                    {
                        volumen--;
                    }
                    else if ((teclaVolumen == ConsoleKey.UpArrow) || (teclaVolumen == ConsoleKey.DownArrow))
                    {
                        opcion = 1; // 1 = ATRÁS.
                    }
                }
                else // No. Mientras.
                {
                    // Navegar entre ATRÁS e INICIO.
                    if ((teclaVolumen == ConsoleKey.LeftArrow) && (opcion == 2))
                    {
                        opcion = 1; // 1 = ATRÁS.
                    }
                    else if ((teclaVolumen == ConsoleKey.RightArrow) && (opcion == 1))
                    {
                        opcion = 2; // 2 = INICIO.
                    }
                    else if ((teclaVolumen == ConsoleKey.UpArrow) || (teclaVolumen == ConsoleKey.DownArrow))
                    {
                        opcion = 0; // 0 = Volumen.
                    }
                }

                // Mostrar menú.
                MostrarMenu();

            } while (teclaVolumen != ConsoleKey.Enter);

            // Acción al pulsar Enter.
            if (opcion == 1)
            {
                // ATRÁS.
                _0_Ajustes.AjustesPrincipal();
            }
            else if (opcion == 2)
            {
                // INICIO.
                Inicio.InicioPrincipal();
            }

            // Mostrar dibujado en pantalla.
            void MostrarVolumen()
            {
                Console.SetCursorPosition(0, 0);
                Console.Write(TEXTO[0]);           //    ** VOLUMEN ** 

                Console.SetCursorPosition(1, 1);
                Console.Write(TEXTO[1]);           //   Vol:

                for (int i = 0; i < volumen; i++)
                {
                    Console.Write(TEXTO[2]);       // ■
                }

                for (int j = 0; j < (VOLMEN_MAX - volumen); j++)
                {
                    Console.Write(TEXTO[3]);       // -
                }

                // Mostrar el volumen en número.
                Console.SetCursorPosition(16, 1);
                Console.Write(volumen);
            }

            void MostrarMenu()
            {
                Console.SetCursorPosition(2, 3);
                Console.Write(TEXTO[4]);           //   ATRÁS

                Console.SetCursorPosition(13, 3);
                Console.Write(TEXTO[5]);           //   INICIO

                Console.SetCursorPosition(0, 1);
                Console.Write(TEXTO[7]);           //
                Console.SetCursorPosition(0, 3);
                Console.Write(TEXTO[7]);           //
                Console.SetCursorPosition(11, 3);
                Console.Write(TEXTO[7]);           //

                // ¿Es 0 = Volumen?
                if (opcion == 0)
                {
                    // Sí. Indica esta posición del cursor.
                    Console.SetCursorPosition(0, 1);
                }

                // No. Entonces, ¿ 1 = ATRÁS?
                else if (opcion == 1)
                {
                    // Sí. Indica esta posición del cursor.
                    Console.SetCursorPosition(0, 3);
                }

                // No. Entonces, ¿2 = INICIO?
                else if (opcion == 2)
                {
                    // Sí. Indica esta posición del cursor.
                    Console.SetCursorPosition(11, 3);
                }

                // Muestra el caracter >.
                Console.Write(TEXTO[6]);  //   >
            }
        }
    }
}

AjustesPrincipal():
Insertar CODE, HTML o PHP:
//    ** AJUSTES **        
// > Volumen.
//   Brillo/Contraste  
//   [x] Beep. 

//    ** AJUSTES **         
// > [x] Luz de fondo.
//   ATRÁS
//   INICIO

using LCD_Menu_con_submenus_Consola_03.Ventana03;
using System;

namespace LCD_Menu_con_submenus_Consola_03.Ventana01
{
    public class _0_Ajustes
    {
        public static void AjustesPrincipal()
        {
            string[] TEXTO =
            {
                "   ** AJUSTES **    ", // Posición 0.
                "  Volumen.          ", // 1
                "  Brillo / Contraste", // 2
                "  [ ] Beep          ", // 3
                "  [ ] Luz de fondo. ", // 4
                "  ATRÁS             ", // 5
                "  INICIO            ", // 6
                ">",                    // 7
                "x",                    // 8
                " "                     // 9
            };

            // Contador de teclas y navegador.
            sbyte indiceSeleccionado = 0;                   // Índice seleccionado de cada opción del menú.
            bool salir = false;                             // Para salir del menú principal al INICIO.
            const sbyte SELECCION_OPCIONES_TOTALES = 5;     // Total de opciones para seleccionar y fija.

            // Capturar tecla para luego validar.
            ConsoleKey tecla;

            do
            {
                //******************************************************************
                // Dibujo el menú principal.

                switch (indiceSeleccionado)
                {
                    case 0:
                        Console.SetCursorPosition(0, 0);
                        Console.Write(TEXTO[0]);         //     ** AJUSTES **    
                        Console.SetCursorPosition(0, 1);
                        Console.Write(TEXTO[1]);         // > Volumen.            
                        Console.SetCursorPosition(0, 1);
                        Console.Write(TEXTO[7]);         // >
                        Console.SetCursorPosition(0, 2);
                        Console.Write(TEXTO[2]);         //   Brillo / Contraste      
                        Console.SetCursorPosition(0, 3);
                        Console.Write(TEXTO[3]);         //   [ ] Beep.             
                        break;

                    case 1:
                        Console.SetCursorPosition(0, 0);
                        Console.Write(TEXTO[0]);         //     ** AJUSTES **  
                        Console.SetCursorPosition(0, 1);
                        Console.Write(TEXTO[1]);         //   Volumen.  
                        Console.SetCursorPosition(0, 2);
                        Console.Write(TEXTO[2]);         // > Brillo / Contraste      
                        Console.SetCursorPosition(0, 2);
                        Console.Write(TEXTO[7]);         // >
                        Console.SetCursorPosition(0, 3);
                        Console.Write(TEXTO[3]);         //   [ ] Beep.   
                        break;

                    case 2:
                        Console.SetCursorPosition(0, 0);
                        Console.Write(TEXTO[0]);         //     ** AJUSTES **  
                        Console.SetCursorPosition(0, 1);
                        Console.Write(TEXTO[1]);         //   Volumen.  
                        Console.SetCursorPosition(0, 2);
                        Console.Write(TEXTO[2]);         //   Brillo / Contraste      
                        Console.SetCursorPosition(0, 3);
                        Console.Write(TEXTO[3]);         // > [ ] Beep.   
                        Console.SetCursorPosition(0, 3);
                        Console.Write(TEXTO[7]);         // >
                        break;

                    case 3:
                        Console.SetCursorPosition(0, 0);
                        Console.Write(TEXTO[0]);         //     ** AJUSTES **  
                        Console.SetCursorPosition(0, 1);
                        Console.Write(TEXTO[4]);         // >  [ ] Luz de fondo.
                        Console.SetCursorPosition(0, 1);
                        Console.Write(TEXTO[7]);         // >        
                        Console.SetCursorPosition(0, 2);
                        Console.Write(TEXTO[5]);         //    ATRÁS
                        Console.SetCursorPosition(0, 3);
                        Console.Write(TEXTO[6]);         //    INICIO
                        break;

                    case 4:
                        Console.SetCursorPosition(0, 0);
                        Console.Write(TEXTO[0]);         //     ** AJUSTES **  
                        Console.SetCursorPosition(0, 1);
                        Console.Write(TEXTO[4]);         //   [ ] Luz de fondo.
                        Console.SetCursorPosition(0, 2);
                        Console.Write(TEXTO[5]);         // > ATRÁS       
                        Console.SetCursorPosition(0, 2);
                        Console.Write(TEXTO[7]);         // >
                        Console.SetCursorPosition(0, 3);
                        Console.Write(TEXTO[6]);         //    INICIO
                        break;

                    case 5:
                        Console.SetCursorPosition(0, 0);
                        Console.Write(TEXTO[0]);         //     ** AJUSTES **  
                        Console.SetCursorPosition(0, 1);
                        Console.Write(TEXTO[4]);         //   [ ] Luz de fondo.
                        Console.SetCursorPosition(0, 2);
                        Console.Write(TEXTO[5]);         //   ATRÁS       
                        Console.SetCursorPosition(0, 3);
                        Console.Write(TEXTO[6]);         // > INICIO
                        Console.SetCursorPosition(0, 3);
                        Console.Write(TEXTO[7]);         // >
                        break;

                    default:
                        Console.Write("Fuera de rango.     ");
                        break;
                }

                // Fin de pintar el menú principal.
                //******************************************************************

                // Leer tecla ingresada por el usuario.
                tecla = Console.ReadKey(true).Key;

                // Validar el tipo de tecla.
                if (tecla == ConsoleKey.Enter)
                {
                    switch (indiceSeleccionado)
                    {
                        case 0:
                            _0_Volumen.Volumen();
                            break;

                        case 1:

                            break;

                        case 2:

                            break;

                        case 3:

                            break;

                        case 4:
                            salir = true;
                            break;

                        case 5:
                            Inicio.InicioPrincipal();
                            break;

                        default:
                            Console.Write("Fuera de rango.     ");
                            break;
                    }
                }

                // ¿Has pulsado tecla flecha Abajo?
                if (tecla == ConsoleKey.DownArrow)
                {
                    indiceSeleccionado++;
                }

                // Entonces si pulsas tecla flecha Arriba.
                if (tecla == ConsoleKey.UpArrow)
                {
                    indiceSeleccionado--;
                }

                // Si está en la última opción, salta a la primera.
                if (indiceSeleccionado > SELECCION_OPCIONES_TOTALES)
                {
                    indiceSeleccionado = 0;
                }

                // Si está en la primera posición, salta a la última.
                if (indiceSeleccionado < 0)
                {
                    indiceSeleccionado = SELECCION_OPCIONES_TOTALES;
                }

                // Salida del menú.
            } while (salir == false);
        }
    }
}

Llevo tiempo sin resolver esto.

Espero que se entienda lo que quiero decir, si no, se lo explico con más capturas.

Muchas gracias.
 

AwBoost

VIP
Gamma
Programador
Verificación en dos pasos activada
Verificado por Whatsapp
Suscripción a IA
Desde
22 Abr 2024
Mensajes
199
En tu código, cuando el usuario selecciona "ATRÁS" en el método Volumen(), llamas a AjustesPrincipal(). Luego, en AjustesPrincipal(), si el usuario selecciona "Volumen", se llama nuevamente a Volumen().
 

Meta

Alfa
Usuario nuevo
¡Usuario con pocos negocios! ¡Utiliza siempre saldo de Forobeta!
Desde
6 Ago 2024
Mensajes
15
Será eso, debería terminar el método el que sea cuando entre en otro.

Desde que esté en Volumen(), es en esta ventana.
LCD-Volumen-02.jpg


Selecciono > ATRÁS y pulso Enter, luego se va a la otra ventana indicada abajo.
LCD-Volumen-03.jpg


Selecciono > ATRÁS otra vez y se me vuelve a la ventana de la primera imagen del método Volumen() cuando en realidad debe ir a otra ventana del método ConfiguracionPrincipal().
LCD-Volumen-04.jpg


¿Hay alguna solución?
 

Meta

Alfa
Usuario nuevo
¡Usuario con pocos negocios! ¡Utiliza siempre saldo de Forobeta!
Desde
6 Ago 2024
Mensajes
15
Lo he hecho, se crea pila de llamada.

Tal vez tenga que empezar desde cero, eso de llamar un void, dentro de otro void en C#, si no cierras ese void como debe ser, porque, me voy a otro void para arriba y para abajo...

Como no se cierra, se me desborda con el tiempo, de tanto usarlo, la pila de llamada.

Está claro que el problema es la pila de llamadas.

Por ejemplo, en este vídeo si entro y salgo de muchos void que suele ser cada ventana con sus funciones o sin ellas.


¿Cuál es la mejor forma de hacer un programa que por cada llamada void, es una ventana con funciones?
 

AwBoost

VIP
Gamma
Programador
Verificación en dos pasos activada
Verificado por Whatsapp
Suscripción a IA
Desde
22 Abr 2024
Mensajes
199
Lo he hecho, se crea pila de llamada.

Tal vez tenga que empezar desde cero, eso de llamar un void, dentro de otro void en C#, si no cierras ese void como debe ser, porque, me voy a otro void para arriba y para abajo...

Como no se cierra, se me desborda con el tiempo, de tanto usarlo, la pila de llamada.

Está claro que el problema es la pila de llamadas.

Por ejemplo, en este vídeo si entro y salgo de muchos void que suele ser cada ventana con sus funciones o sin ellas.


¿Cuál es la mejor forma de hacer un programa que por cada llamada void, es una ventana con funciones?

Intenta ayudarte con chatgpt para que te ordene correctamente el codigo, no es complicado asi que creo que a la primera te puede refactorizar el codgo y alli mismo veras como se debe hacer.
 

Meta

Alfa
Usuario nuevo
¡Usuario con pocos negocios! ¡Utiliza siempre saldo de Forobeta!
Desde
6 Ago 2024
Mensajes
15
 

kj2

Kappa
Verificación en dos pasos activada
¡Ha verificado su Paypal!
Verificado por Binance
Desde
1 Abr 2011
Mensajes
2.662
Me cuesta un poco entender el contexto, ya que desde el comienzo preguntas de una manera poco clara, con lo cual dudo que chatgpt, google o una persona pueda ayudarte fácilmente.

Hasta donde comprendo, dices que entras el una llamada que itera en en la misma función... eso no tendría que ser un problema siempre que no sea infinito ¿Es infinito? - Porque pila que muestras en la captura no se ve tan grande como para generar un overflow.

¿O lo que quieres es evitar ese bucle? Porque si es para algo de uso intensivo seguro sería un problema y eso puede generar que se rompa el programa, o quizá lo que pasa es que se está rompiendo... eso no lo sé comprender porque hace años que no uso un IDE para programar (Editor de texto y errores en terminal solamente) y aunque los usara existen varios, por lo que visualmente no lo podría identificar a menos que use el mismo que el tuyo.

Si lo que quieres es evitar que el stack vaya creciendo de esa manera y que haya una llamada en bucle, hay soluciones como que en lugar de hacer simples llamadas, retornes callables o null.

El primero del stack llama siempre que reciba un callable hasta que recibe null que indicaría que se encuenta en el menú inicial y solo hay que seguir ejecutandolo y no llamar a nada. De ese modo tu stack de calls nunca haría loop.

kj
 
Última edición:

Meta

Alfa
Usuario nuevo
¡Usuario con pocos negocios! ¡Utiliza siempre saldo de Forobeta!
Desde
6 Ago 2024
Mensajes
15
Ya se el motivo, otra historia es resolver el problema.

Lo que pasa, es que al entrar al void Volumen(), antes debo terminar esta función, en vez de terminarla, lo que hago es que voy a otro void llamado en este caso _0_Ajustes.AjustesPrincipal(); que es la selección > ATRÁS, por eso no borra la pila de llamada de Volumen().

Debo terminar el void y luego llamo otro fuera, no desde dentro, de lo contrario, al pulsar > ATRÁS, no va al _0_Ajustes.AjustesPrincipal(); indicado, si no retrocede al Volumen(); me vuelve a retornar en lo último.

Por ejemplo, estoy en una ventana 2, quiero ir atrás que es el 1 y va y vuelve al 2. Está mal. Debo implementar más el tema de la pila de llamadas para que el programa no se comporte con cosas raras.

El programa es modular, usa página o ventanas a otras. Es como usar Windows Form que no hay ningún tipo de problemas, si llamo a un form a otro form, en modo consola si da problemas por todas partes.

Otra opción no recomendable, es usar el no recomendado Goto, este si que no usa pila de llamadas ni nada de eso, solo etiquetas.

Mirando bien, hay que usar las instrucciones de salto como indica aquí, toca averiguar la mejor adecuada.


Gracias.
 
Arriba