Vixente

UI Asincrona

Aug 9th, 2013
259
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 5.02 KB | None | 0 0
  1. public partial class Form1 : Form
  2.     {
  3.         // El delegado que vamos a usar para invocar con BeginInvoke...
  4.         public delegate void Invokador();
  5.  
  6.         public Form1()
  7.         {
  8.             InitializeComponent();
  9.  
  10.             //Cambiamos la barra para que esté animada desde que se carga el form
  11.             barra.Style = ProgressBarStyle.Marquee;
  12.         }
  13.  
  14.         // Función que se encarga de actualizar el texto tratandolo como si estuviera en el mismo hilo
  15.         public void actualizaTexto()
  16.         {
  17.             Texto.Text += "TEXTO ";
  18.         }
  19.  
  20.         // Función para limpiar el texto
  21.         public void limpiaTexto()
  22.         {
  23.             Texto.Text = "";
  24.         }
  25.  
  26.         // Función que comprueba si necesitamos invocar (Estamos en otro hilo?) y entonces invoca al delegado el cual recibe una
  27.         // lambda ( () => ) la cual llama a la funcion que actualiza el texto (en ese punto ya estamos en el hilo principal)
  28.         public void actualizaTextoAsincronamente()
  29.         {
  30.             if (Texto.InvokeRequired) Texto.BeginInvoke(new Invokador(() => actualizaTexto()));
  31.             // Si sabes seguro que estas en otro hilo, te puedes ahorrar el InvokeRequired, pero a mi me gusta ponerlo...
  32.         }
  33.    
  34.         // Botón que actualiza el texto de manera sincrónica, congelando la UI.
  35.         private void ButSincrono_Click(object sender, EventArgs e)
  36.         {
  37.             limpiaTexto();
  38.  
  39.             for (int i = 0; i < 100; i++)
  40.             {
  41.                 Thread.Sleep(50);       // Espera 50 milisegundos en cada iteración, esto acentúa el congelamiento.
  42.                 actualizaTexto();
  43.             }
  44.         }
  45.  
  46.         // Función que crea un hilo paralelo, llamando al delegado que llama a una lambda, la cual llama a la función para actualizar
  47.         // el texto desde otro thread distinto.
  48.         private void ButThread_Click(object sender, EventArgs e)
  49.         {
  50.             limpiaTexto();
  51.  
  52.             Thread hilo = new Thread(new ThreadStart( () => ejecutaBucleAsincronamente() )); // Aquí declaramos el hilo.
  53.             hilo.Start();   // Aquí arrancamos el hilo.
  54.         }
  55.  
  56.         // Adaptación asincrona del bucle que se encarga de actualizar el texto. (Se usa siempre que sepamos que estamos en otro hilo)
  57.         private void ejecutaBucleAsincronamente()
  58.         {
  59.             for (int i = 0; i < 100; i++)
  60.             {
  61.                 Thread.Sleep(50);       // Espera 50 milisegundos en cada iteración, aquí la congelación la tiene el hilo secundario.
  62.                 actualizaTextoAsincronamente();
  63.             }
  64.         }
  65.  
  66.         // Función que hace uso de Task.Run de .NET 4.5 (En 4.0 es Task.Factory.StartNew) para lanzar una Task directamente, sin tener que declararla
  67.         private void ButTaskRun_Click(object sender, EventArgs e)
  68.         {
  69.             limpiaTexto();
  70.  
  71.             Task.Run( () => ejecutaBucleAsincronamente() );     // Lambdas, lambdas everywhere. :)
  72.         }
  73.  
  74.         // Función que declara una tarea y luego la ejecuta.
  75.         private void ButTask_Click(object sender, EventArgs e)
  76.         {
  77.             limpiaTexto();
  78.  
  79.             Task tarea = new Task( () => ejecutaBucleAsincronamente());
  80.  
  81.             tarea.Start();
  82.  
  83.             // Aquí se muestra como utilizar una sencilla continuación mediante el uso de una lambda que llama a una msgbox.
  84.             // Lo que se le pasa a la lambda entre paréntesis (tareaAnterior) está dentro del contexto de la lambda solamente
  85.             // y sirve para obtener los valores de la tarea anterior, si fuera necesario.
  86.             // Además se muestra como a las lambda se les puede poner llaves para poner más de una instrucción.
  87.  
  88.             tarea.ContinueWith( (tareaAnterior) => {
  89.                
  90.                 // Para mostrar el uso de valores de la tarea anterior, se obtiene el bool de si esa tarea fue o no completada.
  91.                 MessageBox.Show(tareaAnterior.IsCompleted.ToString(),"HECHO!");
  92.  
  93.             });     // Al cerrar las llaves de la lambda, seguimos teniendo que cerrar los paréntesis de la llamada a ContinueWith.
  94.         }
  95.  
  96.  
  97.         // Pequeño ejemplo de como hacer un par de llamadas a async
  98.         private void ButAsync_Click(object sender, EventArgs e)
  99.         {
  100.             limpiaTexto();
  101.             Bucle();
  102.         }
  103.  
  104.         // Bucle está declarada como async pero en la función anterior se la llama sincrónicamente...
  105.         public async void Bucle()
  106.         {
  107.             for (int i = 0; i < 1000; i++)
  108.                 // Aguardamos a la Task que actualiza el texto.
  109.                 await actualizaTextoAsync();
  110.         }
  111.  
  112.         // Esta función es una tarea, porque para usar await se ha de hacer contra funciones u objetos que devuelvan o sean Task.
  113.         public async Task actualizaTextoAsync()
  114.         {
  115.                 await Task.Delay(50);   // Aguardamos un retardo de 50 ms.
  116.                 actualizaTexto();       // Actualizamos el texto tranquilamente, de manera normal. ;)
  117.         }
  118.  
  119.  
  120.  
  121.     }   // Form1
Add Comment
Please, Sign In to add comment