none
Salir de un bucle for al pulsar un boton RRS feed

  • Pregunta

  • Buenas noches,

    tengo un proyectos con 2 clases, form1.cs y funciones.cs.

    La cuestión es que en funciones.cs, tengo un bucle for dentro de una función, y en form1 tengo un botón que quiero que cuando se haga click se rompa el bucle. Lo estoy intentando un una variable buleana y break, pero no consigo hacerlo.

    Lo he conseguido declarando la variable en el form1 así: public static bool verd = true; y luego dentro del for hago: if (verd == false) { break; }, pero no me gusta declarar así la variable.

    ¿Como puedo lograr que al hacer click en el botón, cambie el valor de la variable de la otra clase?

    Muchas gracias.

    domingo, 31 de agosto de 2014 2:57

Respuestas

  • Lo que quieres hacer es más complicado de lo que parece. Necesitarás utilizar programación en multi-hilo, porque de lo contrario el formulario queda "congelado" mientras se está ejecutando el bucle, y por lo tanto el click del botón no se procesa hasta que el bucle ha terminado (y por lo tanto no te sirve para interrumpirlo).

    Una alternativa sencilla es meter una llamada a Application.DoEvents() dentro del bucle. Esto permite que se "libere" el control una vez por cada iteración del bucle y se procese el click en ese momento. Otra alternativa sería usar un BackgroundWorker para ejecutar la función que contiene el bucle. Si sigues esta última vía, el propio BackGroundWorker tiene la funcionalidad de pasar una variable indicando que quieres interrumpir la operación, por lo que no necesitas declararla por separado.

    Pero si sigues la primera vía, entonces es válido lo que has hecho de daclarar la variable como public static bool verd. Desde la otra clase, se accede a ella mediante if (!form1.verd) break;

    Nótese que para acceder a la variable estática hay que anteponerle el nombre de la clase en la que se declaró.

    • Marcado como respuesta Bulldovi domingo, 31 de agosto de 2014 15:37
    domingo, 31 de agosto de 2014 9:41
  • Podrías ver algo así

    using System;
    using System.Windows.Forms;
    
    namespace WindowsFormsApplication1
    {
        public partial class Form1 : Form
        {
            private Funciones Func;
    
            public Form1()
            {
                InitializeComponent();
            }
    
            private void button1_Click(object sender, EventArgs e)
            {
                ((Button)sender).Enabled = false;
                Func = new Funciones();
                Func.Cancelar = false;
                Func.CicloInfinito();
                Func = null;
                ((Button)sender).Enabled = true;
            }
    
            private void button2_Click(object sender, EventArgs e)
            {
                if (Func != null) Func.Cancelar = true;
            }
    
            private void Form1_FormClosing(object sender, FormClosingEventArgs e)
            {
                if (Func != null) Func.Cancelar = true;
            }
    
        }
    
        public class Funciones
        {
            public bool Cancelar { get; set; }
    
            public void CicloInfinito()
            {
                for (; !Cancelar; Application.DoEvents())
                {
    		// evita consumir todo el tiempo de procesador
    		// puedes quitarla si quieres que consuma todo el ancho de banda posible
                    System.Threading.Thread.Sleep(5);
                }
            }
        }
    }
    


    [W]

    • Marcado como respuesta Bulldovi domingo, 31 de agosto de 2014 15:43
    domingo, 31 de agosto de 2014 13:26

Todas las respuestas

  • Lo que quieres hacer es más complicado de lo que parece. Necesitarás utilizar programación en multi-hilo, porque de lo contrario el formulario queda "congelado" mientras se está ejecutando el bucle, y por lo tanto el click del botón no se procesa hasta que el bucle ha terminado (y por lo tanto no te sirve para interrumpirlo).

    Una alternativa sencilla es meter una llamada a Application.DoEvents() dentro del bucle. Esto permite que se "libere" el control una vez por cada iteración del bucle y se procese el click en ese momento. Otra alternativa sería usar un BackgroundWorker para ejecutar la función que contiene el bucle. Si sigues esta última vía, el propio BackGroundWorker tiene la funcionalidad de pasar una variable indicando que quieres interrumpir la operación, por lo que no necesitas declararla por separado.

    Pero si sigues la primera vía, entonces es válido lo que has hecho de daclarar la variable como public static bool verd. Desde la otra clase, se accede a ella mediante if (!form1.verd) break;

    Nótese que para acceder a la variable estática hay que anteponerle el nombre de la clase en la que se declaró.

    • Marcado como respuesta Bulldovi domingo, 31 de agosto de 2014 15:37
    domingo, 31 de agosto de 2014 9:41
  • Podrías ver algo así

    using System;
    using System.Windows.Forms;
    
    namespace WindowsFormsApplication1
    {
        public partial class Form1 : Form
        {
            private Funciones Func;
    
            public Form1()
            {
                InitializeComponent();
            }
    
            private void button1_Click(object sender, EventArgs e)
            {
                ((Button)sender).Enabled = false;
                Func = new Funciones();
                Func.Cancelar = false;
                Func.CicloInfinito();
                Func = null;
                ((Button)sender).Enabled = true;
            }
    
            private void button2_Click(object sender, EventArgs e)
            {
                if (Func != null) Func.Cancelar = true;
            }
    
            private void Form1_FormClosing(object sender, FormClosingEventArgs e)
            {
                if (Func != null) Func.Cancelar = true;
            }
    
        }
    
        public class Funciones
        {
            public bool Cancelar { get; set; }
    
            public void CicloInfinito()
            {
                for (; !Cancelar; Application.DoEvents())
                {
    		// evita consumir todo el tiempo de procesador
    		// puedes quitarla si quieres que consuma todo el ancho de banda posible
                    System.Threading.Thread.Sleep(5);
                }
            }
        }
    }
    


    [W]

    • Marcado como respuesta Bulldovi domingo, 31 de agosto de 2014 15:43
    domingo, 31 de agosto de 2014 13:26
  • Lo que quieres hacer es más complicado de lo que parece. Necesitarás utilizar programación en multi-hilo, porque de lo contrario el formulario queda "congelado" mientras se está ejecutando el bucle, y por lo tanto el click del botón no se procesa hasta que el bucle ha terminado (y por lo tanto no te sirve para interrumpirlo).

    Una alternativa sencilla es meter una llamada a Application.DoEvents() dentro del bucle. Esto permite que se "libere" el control una vez por cada iteración del bucle y se procese el click en ese momento. Otra alternativa sería usar un BackgroundWorker para ejecutar la función que contiene el bucle. Si sigues esta última vía, el propio BackGroundWorker tiene la funcionalidad de pasar una variable indicando que quieres interrumpir la operación, por lo que no necesitas declararla por separado.

    Pero si sigues la primera vía, entonces es válido lo que has hecho de daclarar la variable como public static bool verd. Desde la otra clase, se accede a ella mediante if (!form1.verd) break;

    Nótese que para acceder a la variable estática hay que anteponerle el nombre de la clase en la que se declaró.

    Muchas gracias. Así lo tengo, pero aún no lo he probado. No obstante, quiero mirar la alternativa que propones.

    Saludos,

    domingo, 31 de agosto de 2014 15:37
  • Podrías ver algo así

    using System;
    using System.Windows.Forms;
    
    namespace WindowsFormsApplication1
    {
        public partial class Form1 : Form
        {
            private Funciones Func;
    
            public Form1()
            {
                InitializeComponent();
            }
    
            private void button1_Click(object sender, EventArgs e)
            {
                ((Button)sender).Enabled = false;
                Func = new Funciones();
                Func.Cancelar = false;
                Func.CicloInfinito();
                Func = null;
                ((Button)sender).Enabled = true;
            }
    
            private void button2_Click(object sender, EventArgs e)
            {
                if (Func != null) Func.Cancelar = true;
            }
    
            private void Form1_FormClosing(object sender, FormClosingEventArgs e)
            {
                if (Func != null) Func.Cancelar = true;
            }
    
        }
    
        public class Funciones
        {
            public bool Cancelar { get; set; }
    
            public void CicloInfinito()
            {
                for (; !Cancelar; Application.DoEvents())
                {
    		// evita consumir todo el tiempo de procesador
    		// puedes quitarla si quieres que consuma todo el ancho de banda posible
                    System.Threading.Thread.Sleep(5);
                }
            }
        }
    }


    [W]

    Precisamente estoy mirando una alternativa que se me ha ocurrido con las propiedades get set.

    No informé que el lenguaje era c#, de echo creo que no puse la pregunta en el subforo apropiado.

    Nunca he visto un for en c# con puntos y comas......., perdona si es obvio, pero....¿es c# tu código?

    Y muchas gracias

    domingo, 31 de agosto de 2014 15:43
  • Sí es C#

    En este caso equivale a un while con una función que se repite al final del bloque (dos, si agregas el sleep).

    Como la tercera expresión del for se ejecuta luego del final del bloque, usamos un for en vez de un while.


    [W]

    domingo, 31 de agosto de 2014 16:46
  • Nunca he visto un for en c# con puntos y comas

    Es muy común en todos los lenguajes derivados del C: C++, C#, java, javascript...

    La sintaxis es esta:

    for (operación inicial; condición de iteración; instrucción al iterar) {...}

    Lo más frecuente es encontrarse un bucle de este tipo:

    for (i=0; i<N; i++) {...}

    que es el típico bucle que ejecuta N iteraciones contándolas con la variable i.

    Pero jugando con las tres expesiones se pueden lograr comportamientos más sofisticados; por ejemplo, este bucle recorre un rango de fechas:

    for (DateTime f = fechaInicial; f<dechaFinal; f=f.AddDays(1)) {...}

    Cualquiera de las tres expresiones se puede omitir, dejando solo el punto y coma. Por ejemplo, esto es un bucle infinito: for (;;){...}. Equivale a while(true) {...}.

     

    domingo, 31 de agosto de 2014 17:54
  • gracias
    domingo, 31 de agosto de 2014 22:20
  • gracias, si en java si lo había visto, pero en c# siempre lo he visto con ,

    saludos,

    domingo, 31 de agosto de 2014 22:21