Continuando con mi entrada anterior, el detalle que hay que corregir es el siguiente: no se puede modificar la interfaz gráfica desde otro hilo. Las interfaces gráficas de .Net y Java no son thread-safe, incluso estos frameworks arrojarán una excepción si detectan que se está intentando modificar la interfaz gráfica desde otro hilo que no haya sido el que la creó.
Como ejemplo, voy a añadir un par de líneas al final de las funciones Hilo1() e Hilo2() en el código que dejé como ejemplo:
En muchas aplicaciones que modifican la interfaz gráfica es necesario llamar a las funciones Refresh() de los controles. Después de este cambio, la aplicación arroja esta excepción:
La manera correcta, en C#, de modificar la interfaz gráfica desde otro hilo es usando las funciones Invoke() o BeginInvoke() de la plataforma .Net.
Por otro lado, es una mala práctica llamar a la función Abort() de un hilo. Si se desea que un hilo finalice junto a la aplicación que lo creó se debe declarar como hilo de background, eso se hace en una línea de código:
p2.IsBackground = true;
El código corregido es:
using System; using System.Drawing; using System.Text; using System.Windows.Forms; using System.Threading; namespace WindowsApplication1 { public partial class Form1 : Form { Thread p1; Thread p2; byte r, g; bool b1, b2;
public Form1() { InitializeComponent(); } private void Form1_Load(object sender, EventArgs e) { r = 0; g = 255; b1 = false; b2 = true; p1 = new Thread(new ThreadStart(Hilo1)); p2 = new Thread(new ThreadStart(Hilo2)); p1.IsBackground = true; p2.IsBackground = true; p1.Start(); p2.Start(); }
public void Hilo1() { while (true) { Thread.Sleep(10); if (r >= 0 && r <= 255 && b1 == false) { r++; if (r == 255) b1 = true; } if (r >= 0 && r <= 255 && b1 == true) { r--; if (r == 0) b1 = false; } if (this.InvokeRequired) { this.BeginInvoke((Action)(() => { pictureBox1.BackColor = Color.FromArgb(r, 80, 100); pictureBox1.Refresh(); })); } } } public void Hilo2() { while (true) { Thread.Sleep(10); if (g >= 0 && g <= 255 && b2 == false) { g++; if (g == 255) b2 = true; } if (g >= 0 && g <= 255 && b2 == true) { g--; if (g == 0) b2 = false; } if (this.InvokeRequired) { this.BeginInvoke((Action)(() => { pictureBox2.BackColor = Color.FromArgb(100, g, 80); pictureBox2.Refresh(); })); } } } private void Form1_FormClosed(object sender, FormClosedEventArgs e) { } } } |