












Prepara tus exámenes y mejora tus resultados gracias a la gran cantidad de recursos disponibles en Docsity
Gana puntos ayudando a otros estudiantes o consíguelos activando un Plan Premium
Prepara tus exámenes
Prepara tus exámenes y mejora tus resultados gracias a la gran cantidad de recursos disponibles en Docsity
Prepara tus exámenes con los documentos que comparten otros estudiantes como tú en Docsity
Encuentra los documentos específicos para los exámenes de tu universidad
Estudia con lecciones y exámenes resueltos basados en los programas académicos de las mejores universidades
Responde a preguntas de exámenes reales y pon a prueba tu preparación
Consigue puntos base para descargar
Gana puntos ayudando a otros estudiantes o consíguelos activando un Plan Premium
Comunidad
Pide ayuda a la comunidad y resuelve tus dudas de estudio
Ebooks gratuitos
Descarga nuestras guías gratuitas sobre técnicas de estudio, métodos para controlar la ansiedad y consejos para la tesis preparadas por los tutores de Docsity
Introducción a la programacion en CSharp, tema de Hilos de ejecución en C-Sharp
Tipo: Resúmenes
1 / 20
Esta página no es visible en la vista previa
¡No te pierdas las partes importantes!













CURSO : Electiva de profundización I (desarrollo de software libre) TEMA : Hilos de ejecución en C#. DESCRIPCION : En el presente documento se hace un tratamiento teórico-practico sobre el tema de los hilos de ejecución en el lenguaje de programación C#, desarrollando para ello una aplicación de interfaz grafica de usuario (GUI) construida con Widgets (componentes) de GTK# 2.0 y empleando el entorno integrado de desarrollo (IDE) MonoDevelop para GNU/Linux. El programa de ejemplo se construye implementando una clase que encapsula el comportamiento de un hilo de ejecución que debe realizar una proceso cíclico en paralelo para calcular la sumatoria de los términos de un conjunto de series numéricas de modo que puede apreciarse el progreso dentro de un TreeView y con barras de progreso. La implementación de la clase para la funcionalidad del hilo de ejecución ilustra además la declaración y uso de delegados, como una forma de envió y recepción de eventos y que permite establecer una relación débil entre clases. OBJETIVO : Diseñar e implementar en el lenguaje C# una clase para representar la funcionalidad de un hilo de ejecución, de modo que se pueda usar desde aplicaciones de consola y también de interfaz grafica de usuario, ejemplificando su uso en un programa de ventana que realice cálculos en paralelo de varias sumatorias, mostrando los resultados parciales y finales de esta conjuntamente con una barra de progreso dentro del Widget TreeView. PALABRAS CLAVES : Implementación de clases en C#, uso de delegados, hilos en C#, la clase Thread de C#, Widgets, propiedades y señales, el Widget TreeView.
Un hilo o hilo de ejecución es un concepto que permite implementar en un programa la capacidad de ejecutar dos o más tareas (procesos) de forma paralela, es decir, de manera “simultanea”, de modo que el programa no tenga que esperar a que termine una o más de las tareas iniciadas por el usuario para responder a nuevas solicitudes de este. Se debe entender que dichas tareas son consideradas actividades que comprenden la realización de ciclos que eventualmente pueden tardar, de tal suerte que no deseamos que el programa se “pasme” ante el usuario mientras tales procesos son finalizado, permitiendo así que el usuario pueda hacer otras cosas con nuestro programa; incluyendo claro está la posibilidad de cancelar o abortar la tarea que ejecutamos en paralelo. Al respecto cabe recordar que el concepto de paralelo (ejecutar dos o más tareas o procesos de forma simultánea) es posible siempre que tengamos más de un procesador en nuestra maquina, pues en caso contrario el procesador se conmuta (comparte) con cada proceso y lo hace tan rápido que parece que los procesos funcionan simultáneamente. De otra parte para implementar hilos de ejecución en C# requerimos el ensamblado System.Threading del cual usaremos la clase Thread (hilo) que posee todo lo necesario en materia de propiedades y métodos para permitirnos realizar tareas en paralelo dentro de nuestros programas. Los métodos de interés de la clase Thread para este ejemplo son Strat() , Abort () y Sleep(). No obstante crearemos una clase propia que basada en esta (bajo una relación de composición con el fin de proteger ciertos métodos y propiedades de la clase Thread durante la ejecución del hilo) nos permita modelar y ejecutar una tarea en paralelo de forma cíclica, de modo que la tarea a realizar se reciba como un delegado y que el ciclo contenido dentro del hilo ejecute dicha tarea en intervalos fijos de tiempo y la finalización de dicho ciclo sea controlada con otro delegado. Este diseño siguiere que el delegado que implementa la tarea debe contener el cuerpo de un ciclo, no el ciclo en sí, pues este suponemos lo pone el hilo de la clase que crearemos. Esto no significa que el delegado que implementa la tarea a realizar no pueda tener ciclos, pues si puede tenerlo, pero se recomienda que sean pocos o cortos, o que en su defecto se sincronice bien con el tiempo de espera del hilo. En un caso extremo que no se desee que la tarea se repita porque ya viene con los ciclos para ello, el delegado de continuación del hilo debería retornar un false para que la tarea no sea repetida.
b) Crear una nueva solución: Archivo + nuevo + solución. c) Luego se despliega la siguiente ventana, en la que seleccionamos de la lista de la izquierda el nodo C# y de la lista del centro escogemos proyecto GTK#2.0 y seguidamente indicamos el nombre al proyecto que el caso es Ejem_Hilos, de manera forma opcional con el botón examinar podemos indicar una carpeta distinta a la presentada para guardar el proyecto. De igual forma si marca la opción crear subdirectorio de solución por separado, MonoDevelop creara un subdirectorio adcional para los fuentes de la solución con el mismo nombre de la solución. Finalmente pulse el botón adelante. d) Posteriormente se presenta una ventana en la que puede añadir otros proyectos adicionales y opcionales a la solución, tales como soporte GTK#, proyecto de traducción e integración con Unix. Para este caso ninguna de estas opciones son necesarias y por ello no debe marcarlas. La ventana siguiente se observan estas opciones y se aprecia una descripción de cada una de ellas.
La siguiente pantalla ilustra el estado inicial de la solución, donde en el panel izquierdo vemos el inspector de la solución, mostrando las referencias (ensamblados externos) y las clases que componen el proyecto, para este caso el archivo principal Main.cs que contiene la clase MainClass presentada en el panel de la derecha. También vemos que la definición de la clase se encuentra dentro de un nombre de espacio ( namespace ) llamado Ejem_Hilos, que es mismo nombre de la solución. En la implementación del método estático Main vemos una notable diferencia en cuanto a la implementación del mismo para una aplicación de consola, pues se usa el ensamblado Gtk, además de utilizar el objeto Application llamándose algunos de sus métodos, además se crea una instancia de la clase MainWindow que representa la ventana principal, de la cual podemos ver su archivo de código fuente llamado MainWindow.cs como se indica en la figura siguiente.
Ahora haga doble click en el panel de la solución sobre el archivo MainWindow.cs desplegándose la siguiente ventana del código fuente de esta: En la parte inferior de esta ventana observamos dos botones o vistas de la misma, que nos permiten alternar entre el código fuente de la ventana y el diseño visual o grafico de la misma (botón diseñador).
Cuando haga click en el botón diseñador debe ver una imagen previa de la ventana como esta:
4. IMPLEMENTACION DE LA CLASE THILO Haga doble click en el nombre del archivo THilo.cs de la solución y asegúrese de que el código de este archivo sea como sigue: using System; using System.Threading; public delegate void TOnTarea(); public delegate bool TOnContinuar(); public class THilo{ private int FPausa; private TOnTarea FTarea; private TOnContinuar FContinuar; private Thread FHilo; public THilo(){ FPausa= 0 ; FTarea= null ; FContinuar= null ; FHilo= null ; }
En la implementación de esta clase observamos que usamos el ensamblado System. Threading que es que contiene la definición de la clase Thread en base a la cual se desarrolla toda la lógica del funcionamiento del hilo. Como otro aspecto importante que vemos en el código de la clase THilo , es la definición de dos delegados uno tipo void que es empleado para guardar la implementación de la tarea o proceso que se va a ejecutar en paralelo. Así mismo tenemos un delegado de tipo bool que indicara cuando continuar repitiendo la tarea o en su defecto en qué momento se terminara la misma. Note que este delegado se utiliza para controlar el ciclo que se encuentra en el método procesar que es el que se realiza con el hilo.
5. DISEÑO DE LA VENTANA Haga doble click en el nombre del archivo MainWindow.cs de la solución y asegúrese de estar en la vista de diseño de esta. Para diseñar la ventana será necesario usar la barra de herramientas y el inspector de propiedades. Para ver estos, nos vamos por la opción Ver del menú principal y hacemos click en el ítem Visual Design, como se indica en la imagen de izquierda. La imagen de la derecha muestra el panel de componentes (barra de herramientas) y debajo de esta el inspector de propiedades con dos fichas en su parte superior: Propiedades y señales (para programar los eventos). Si aun asi no vemos estos paneles puede seleccionarlos entrando por la opción Ver + Paneles y marcando Barra de herramientas y después propiedades respectivamente.
a) Seleccione la ventana y en el inspector de propiedades despliegue el nodo Window Properties (haciendo click en la flecha a la izquierda de este). Ubique la propiedad Title (Titulo de la ventana) y escriba delante de esta Ejemplo hilos, quedando la ventana como se muestra a continuación. b) Ahora en la barra de herramientas asegúrese de estar en el grupo de contenedores y desde este arrastre hasta la ventana un widget llamado VBox que nos divide la ventana en tres (por defecto) paneles horizontales, como se aprecia en la siguiente imagen.
f) Seguidamente en las tres primeras celdas de la primera fila de la tabla vamos a arrastrar tres Widgets Label que se encuentran en el grupo componentes de la barra de herramientas. A estas tres etiquetas póngales por título Max uno, Max dos y Max tres respectivamente, seleccionándolas individualmente y en el inspector de propiedades expanda el nodo Label Properties y escriba el texto adecuado en la propiedad LabelProp, como se aprecia en la imagen para el caso del tercer Label. g) Ahora hasta las tres primeras celdas de la segunda fila de la tabla arrastre tres Widgets Entry del grupo componentes de la barra de herramientas. A estos tres campos de textos póngales por nombre (propiedad Name en el inspector de propiedades) E1, E2 y E3 seleccionándolos individualmente. Además en el inspector de propiedades para cada Entry expanda el nodo Common Widget Properties y
ubicándose en la propiedad WidthRequest (ancho del componente) marque la casilla de verificación (chéquela) que está al frente y póngale el valor de 70 (media en pixeles) como puede ver en la imagen siguiente para el caso del tercer Entry. h) Arrastre de la barra de herramientas del grupo de componentes un Button hasta la celda superior derecha de la tabla y en el inspector de propiedades asegúrese de expandir el nodo Button Properties, asignando a la propiedad Button Type el valor Text and Icon, con el fin de que el botón además de un titulo pueda exhibir un icono junto a este. En la propiedad Icon haga click en el botón de tres puntos que está a la derecha de esta y seleccione el icono (para el ejemplo gtk-apply). En la propiedad Label escriba el texto del botón, que para este ejemplo es iniciar como se puede observar en la siguiente imagen.
j) Finalmente en el panel inferior arrastre un componente TreeView al cual en la propiedad Name asígnele Trv.
6. IMPLEMENTACION DE LA VENTANA Pase ahora a la vista de código fuente de la ventana, dentro de la cual declaramos como atributos privados a Max1, Max2 y Max3 de tipo int (entero) para guardar en ellos los valores ingresados en los Entry E1, E2 y E3 respectivamente, que representan el numero de términos que se sumaran para cada una de las tres series. El atributo entero Pos lo usamos para determinar el término i-esimo de cada serie además de participar en el cálculo de porcentaje de progreso de cada serie. Este mismo atributo sirve para establecer cuando el hilo debe terminar lo cual se aprecia en el método Seguir() que responde a la firma del delegado TOnContinuar requerido por la clase THilo. De especial atención es el código del método CrearColumnas(), en donde se inicializa el modelo del TreeView con tres columnas de tipo string (cadena), int (entero) y double (real), además observe la forma en la que se crean las columnas, como se asocian esta a las columnas del modelo y los objetos de renderizado (dibujado) que se usan para cada columna con sus respectivas propiedades.
using System; using Gtk; public partial class MainWindow : Gtk.Window { private int Pos; private THilo Hilo; private ListStore Mod; private int Max1,Max2,Max3; public MainWindow () : base (Gtk.WindowType.Toplevel){ Build(); Hilo= null ; CrearColumnas(); } private void CrearColumnas(){ Mod= new ListStore( typeof ( string ), typeof ( double ), typeof ( int )); Trv.AppendColumn( new TreeViewColumn("Operacion", new CellRendererText(),"text", 0 )); Trv.AppendColumn( new TreeViewColumn("Resultado", new CellRendererText(),"text", 1 )); Trv.AppendColumn( new TreeViewColumn("Progreso", new CellRendererProgress(),"value", 2 )); Trv.Model=Mod; } private void IniciarModelo(){ Mod.Clear(); Mod.AppendValues("Suma 2i",0.0, 0 ); Mod.AppendValues("Suma i/2 + 1",0.0, 0 ); Mod.AppendValues("Suma 2i/3 + 1",0.0, 0 ); } private void IniciarHilo(){ Pos= 1 ; Hilo= new THilo(); Hilo.Pausa= 300 ; Hilo.Tarea=CalcSeries; Hilo.Continuar=Seguir; Hilo.Iniciar(); } private void Sumar( int NumFila, int Porcen, double Aumento){ double Actual; TreeIter Fila; Mod.IterNthChild( out Fila,NumFila); Actual=( double )Mod.GetValue(Fila, 1 ); Mod.SetValue(Fila, 1 ,Actual+Aumento); Mod.SetValue(Fila, 2 ,Porcen); }
MonoDevelop genere automáticamente el esqueleto en blanco para codificar el evento, como se muestra en la siguiente figura para el caso del evento click del botón iniciar. Finalmente compile el proyecto, corrija los posibles errores encontrados comparando con lo expuesto en este documento y ejecútelo. La siguiente imagen ilustra una vista de ejecución del programa en acción:
Actividad propuesta. Como complemente del anterior ejercicio desarrolle las siguientes actividades.