Uso de threads en C#

44

Transcript of Uso de threads en C#

Page 1: Uso de threads en C#
Page 2: Uso de threads en C#

Integrantes

Luis Felipe Zacarías GuzmánAlejandro Javier Romero Rosas

Karen Zamora HernándezAna Ivonne Toral Morales

José Guillermo Pájaro CoatlDaniel Alonso CalvarioBruno Salgado Mejía

Page 3: Uso de threads en C#

Funcionamiento de hilos

• Todos los hilos se les asigna un tiempo de

ejecución apropiado y que todos aquellos

hilos que estén bloqueados o pausados no

consuman tiempo de CPU.

• En un ordenador con un solo procesador, un

programador de hilos gestiona una

alternancia rápida entre los hilos activos,

derivando en un comportamiento

entrecortado

• La asignación de tiempo para cada hilo está

en el orden de las decenas de milisegundos.

Page 4: Uso de threads en C#

Hilos y procesos

• Todos los hilos dentro de una aplicación

están dentro de un proceso.

• La diferencia principal es que los procesos

están completamente aislados unos de otros

• los hilos comparten memoria con otros hilos

que pertenecen al mismo proceso

• Un hilo puede estar generando datos en un

segundo plano mientras que otro hilo

muestra los datos que van llegando.

Page 5: Uso de threads en C#

Procesos y subprocesos

• Para que un proceso sea capaz de hacer

• algo, el proceso debe ser propietario de un hilo

(thread).

• Este thread es el responsable de ejecutar el

código contenido en el espacio de direcciones del

proceso.

• un proceso puede contener varios threads y todos

ellos ejecutando código “simultáneamente "en el

espacio de direcciones del proceso

Page 6: Uso de threads en C#

• cada thread tiene su propia colección de

registros de la CPU y su propio stack (pila de

almacenamiento)

• threads se ejecutan concurrentemente al

asignar ‘rodajas de tiempo’ (time slices)

llamadas quantums a cada thread

alternativamente (y consecutivamente).

• cada quantum es de 15 milissegundos.

Page 7: Uso de threads en C#

Administración de procesos

• Process es un componente que nos permite

• Iniciar

• detener

• controlar

• supervisar aplicaciones.

Page 8: Uso de threads en C#

Administración de hebras y hilos

• El ámbito System.Threading proporciona en

la plataforma .NET las clases e interfaces

para escribir código multihebra.

• Cada hebra con un proceso

• Si el proceso crea más hebras, será

multihebra(multithreading)

Page 9: Uso de threads en C#

Por que son útiles las hebras

• En primer lugar, cuando hay una tarea de

fondo. Imagine que quiere poner un logotipo

que gire en la parte superior izquierda del

formulario.

• En segundo lugar, cuando esta realizando

más de una tarea a la vez Podría dividir la

imagen en cuatro partes y ejecutar las

cuatro copias en la rutina de procesado de

imagen

Page 10: Uso de threads en C#

La clase Thread

PROPIEDADES

• CurrentPrincipal

• CurrentThread

• IsAlive

• IsBackground

• Name

• Priority

• ThreadState

Page 11: Uso de threads en C#

METODOS

• Abort

• Interrupt

• Join

• Resume

• Sleep

• Start

• Suspend

Page 12: Uso de threads en C#

Control de las hebras

• Llame a su método Start() para comenzar la

ejecución

• Terminar una hebra puede llamar al método

Abort().

• Los métodos Suspend() y Resume() se pueden

utilizar para parar temporalmente la ejecución

de una hebra y a continuación reiniciarla de nuevo

• Sleep() se utiliza para poner una hebra a dormir

durante un periodo de tiempo, normalmente

especificado como un número de milisegundos.

Page 13: Uso de threads en C#

Estados y prioridad de las hebras

La enumeración ThreadState, describe los posibles estados que puede tener una hebra:

Elementos• Aborted

• AbortRequested

• Background

• Running

• Stopped

• StopRequested

• Suspended

• SuspendRequested

• Unstarted

• WaitSleepJoin

Page 14: Uso de threads en C#

• Un elemento de la enumeración ThreadPriority,

cuyos valores son:

Elemento

• Hightest

• AboveNormal

• Normal.

• BelowNormal

• Lowest

Page 15: Uso de threads en C#

Sincronización de hebras

• compartidos y por la temporización.

• cada función de la hebra tiene su propio

conjunto de variables locales, puesto que las

variables locales se declaran en la pila

• variables locales no pueden interferir con

otras, porque se

• crean en diferentes pilas.

Page 16: Uso de threads en C#

Las clases sin sincronización

• La clase Interlocked contiene cuatro métodos de

hebra segura compartidos para realizar

operaciones con variables

• estos métodos son atómicos, por lo que no se

pueden

• interrumpir por cambios de contexto de hebras:

• Increment: Incrementa una variable.

• · Decrement: Disminuye una variable.

• · Exchange: Pone una variable a un valor y

devuelve el valor original.

• · CompareExchange: Compara dos valores y

reemplaza el valor destino si son iguales

Page 17: Uso de threads en C#

¿Qué es multithreading?

• El multithreading es manejado internamente por un programador de threads, una función que el CLR típicamente delega el sistema operativo.

• Un programador de threads se asegura que todos los threads activos se encuentren apropiadamente dispuestos en tiempo de ejecución, y que los threads que se encuentran bloqueados - por ejemplo por un bloqueo exclusivo, o esperando una entrada del usuario -no consuman recursos de tiempo del CPU.

Page 18: Uso de threads en C#

Threads vs. Procesos

• Todos los threads de una aplicación se encuentran contenidos en proceso – la unidad del sistema operativo en la cual una aplicación corre.

• Los threads tiene ciertas similitudes con los procesos – por ejemplo los procesos corren bajo time-sliced con otros procesos en la computadora de un modo similar a los threads en una aplicación C#.

Page 19: Uso de threads en C#

• La principal diferencia es que los procesos se encuentran totalmente aislados de otros procesos, mientras que los threads comparten el montículo de memoria (heap) con otros threads de la misma aplicación.

• Esto hace que los threads sean muy útiles: un thread puede recuperar datos en segundo plano, mientras que otro thread va mostrando los datos mientras llegan.

Page 20: Uso de threads en C#

¿Cuándo utilizar Threads?

• Una aplicación común para el multithreading es la ejecución en segundo plano de tareas que consumen mucho tiempo. El thread principal se mantiene corriendo mientras que el thread que realiza la operación funciona en segundo plano.

• En aplicaciones Windows Forms, si el thread principal realiza operaciones largas, los mensajes del teclado y el mouse no pueden ser procesados, como resultado la aplicación deja de responder.

Page 21: Uso de threads en C#

• Por esta razón es bueno hacer que las tareas que insumen mucho tiempo funcionen en threads de trabajo y en todo caso el thread principal puede mostrar el diálogo modal “Procesando… espere por favor” en caso que el programa no pueda continuar hasta que la tarea termine.

• Esto asegura que la aplicación no sea tomada por el sistema operativo como "No responde" incitando al usuario a forzar la finalización del proceso!

• El diálogo modal permite implementar un botón "Cancelar" ya que el diálogo continúa recibiendo eventos mientras que la tarea es realizada por el hilo trabajador.

Page 22: Uso de threads en C#

• En el caso de las aplicaciones in interfaz gráfica, como los servicios de Windows, el multithreading toma particular importancia cuando una tarea es potencialmente consumidora de tiempo porque se encuentra a la espera de la respuesta de otra computadora (como un servidor de aplicaciones, un servidor de base de datos, o un cliente).

• Tener un thread trabajador realizando dicha tarea significa que el thread que lo instancia se encontrará inmediatamente libre para hacer otras cosas.

Page 23: Uso de threads en C#

• Otra aplicación del multithreading es utilizarlo en métodos que realizan cálculos intensivos. Tales métodos pueden ejecutarse más rápido en computadoras con múltiples procesadores si la carga de trabajo es dividida en múltiples threads.

• La cantidad de procesadores puede obtenerse por medio de la propiedad Environment.ProcessorCount.

Page 24: Uso de threads en C#

• Una aplicación C# puede convertirse en multithread de dos maneras:

• Creando explícitamente threads adicionales, o utilizando características del framework .NET que implícitamente crean threads – como BackgroundWorker, thread pooling, un threadingtimer, un Remoting server, o un Web Services o una aplicación ASP.NET.

• En estos últimos casos no se tiene control del multithreading.

Page 25: Uso de threads en C#

¿Cuándo no utilizar Threads?

• El multithreading posee desventajas. La más grande es que implica mayor complejidad en los programas. La creación de una aplicación multiples threads no es compleja, la complejidad se encuentra en la interacción entre los threads.

• Esto es así cuando la interacción es válida o no, y puede derivar en largos procesos de desarrollo y la consecuente susceptibilidad de intermitentes y difícilmente reproducibles bugs.

Page 26: Uso de threads en C#

• Por esta razón es recomendable mantener el diseño de la interacción entre los múltiples threads simple – o no utilizar multithreadingl – a menos que tangas una peculiar inclinación por re-ecribir y debuggear!

Page 27: Uso de threads en C#

• El multithreading también implica consumo de recursos y costo de CPU en crear y cambiar entre threads si es utilzado en exceso.

• En particular, cuando implica pesados procesos de lectura/escritura a disco, puede ser más rápido tener uno o dos threads trabajadores realizando las tareas en secuencia en lugar de tener múltiples threads trabajando en simultáneo.

Page 28: Uso de threads en C#

Creando e iniciando Threads

• Los threads utilizando el constructor de la clase Thread, pasándole un delegado del tipo ThreadStart– indicando el método desde donde debe iniciar la ejecución. Aquí vemos la definición del delegado ThreadStart:

• public delegate void ThreadStart();

• Llamando al método Start logramos que la ejecución comience. El thread continúa hasta que su método retorne, en este punto el thread finaliza.

Page 29: Uso de threads en C#

• Aquí vemos un ejemplo utilizando la sintaxis larga de C# para crear el delegado TheadStart:

• class ThreadTest{ static void Main() { Thread t = new Thread (new ThreadStart (Go));t.Start();new thread.Go(); // Corre

simultaneamente Go() en el thread principal. } static void Go() { Console.WriteLine ("hello!"); }

Page 30: Uso de threads en C#

• Se puede crear un thread de un modo más conveniente utilizando la sintaxis corta de C# para instanciar delegados:

• static void Main() { Thread t = new Thread (Go); // No es

necesario utilizar explícitamente ThreadStartt.Start(); ...

}static void Go() { ...

}

Page 31: Uso de threads en C#

• En este caso el delegado ThreadStart es inferido por el compilador. Otro método es utilizar un método anónimo para iniciar un thread:

• static void Main() { Thread t = new Thread (delegate() { Console.WriteLine ("Hello!"); }); t.Start();}

• Un thread tiene su propiedad IsAlive en valor true después de llamar a su método Start(), hasta que el thread finaliza. Una vez finalizado un thread no puede ser re-iniciado.

Page 32: Uso de threads en C#

Pasando datos a ThreadStart

• En ejemplo de arriba queremos distinguir mejor la salida de cada thread, por ejemplo haciendo que uno de ellos imprima en mayúscula.

• Podemos lograr esto pasando un flag al método Go: pero no podemos usar el delegado ThreadStart porque no acepta argumentos. Afortunadamente en framework .NET define otra versión del delegado llamada ParameterizedThreadStart, la cual acepta un objeto como parámetro del siguiente modo:

Page 33: Uso de threads en C#

• public delegate void ParameterizedThreadStart (object obj);

• Entonces el ejemplo previo se ve así:

• class ThreadTest{ static void Main() { Thread t = new Thread (Go); t.Start (true); Go (true) Go (false);

} static void Go (object upperCase) { bool upper = (bool) upperCase; Console.WriteLine (upper ? "HELLO!" : "hello!");

}}

hello!

HELLO!

Page 34: Uso de threads en C#

• En este ejemplo el compilador infiere automáticamente el delegado ParameterizedThreadStart porque el método Goacepta un objeto como argumento.

• Podríamos haberlo escrito:

Thread t = new Thread (new ParameterizedThreadStart (Go));t.Start (true);

Page 35: Uso de threads en C#

Nombrando Threads

• Se puede asignar nombre a un thread a través de su propiedad Name. Esto es de gran beneficio en la depuración: y también permite hacer Console.WriteLine nombre del thread, Microsoft Visual Studio recoge el nombre del thread y lo muestra en la barra de herramientas Debug Location.

• Podemos nombrar un thread en cualquier momento, pero sólo una vez, en caso de intentar cambiar el nombre de un thread obtendremos como resultado una excepción.

Page 36: Uso de threads en C#

• También podemos asignarle nombre al thread principal de la aplicación, en el siguiente ejemplo hacemos esto a través de la propiedad estática CurrentThread:class ThreadNaming{ static void Main() { Thread.CurrentThread.Name = "main"; Thread worker = new Thread (Go); worker.Name = "worker"; worker.Start(); Go();

} static void Go() { Console.WriteLine ("Hello from " + Thread.CurrentThread.Name);

}}

Hello from main

Hello from worker

Page 37: Uso de threads en C#

Threads en primer y segundo plano

• Por defecto los threads corren en primer plano, esto quiere decir que la aplicación siguirácorriendo mientras que alguno de sus threas se encuentre activo.

• C# soporta threads en segundo plano (background threads) los cuales no mantiene la aplicación corriendo por si mismo, sino que terminan inmediatamente cuando la aplicación finaliza.

Page 38: Uso de threads en C#

• Cambiar un thread de primer a segundo plano no cambiar su estado o prioridad en la planificación del CPU de ninguna manera.

La propiedad IsBackground del thread controla el modo de ejecución como en el siguiente ejemplo:

Page 39: Uso de threads en C#

• class PriorityTest{ static void Main (string[] args) { Thread worker = new Thread (delegate() {

Console.ReadLine(); }); if (args.Length > 0) worker.IsBackground = true; worker.Start(); }

}

Page 40: Uso de threads en C#

• Si llamamos al programa sin pasarle argumentos el thread de trabajo corre en su modo por defecto de primer plano y esperará en la instrucción ReadLine hasta que el usuario presione Enter. Mientras tanto el thread principal deja de existir pero la aplicación sigue corriendo porque existe un thread en primer plano todabía vivo.

• Por otro lado, si un argumento es pasado al thread principal (Main()) el thread de trabajo es ejecutado en segundo plano y el programa deja de existir cuando el thread principal termina, finalizando la instrucción ReadLine.

Page 41: Uso de threads en C#

• Cuando un hilo en segundo plano termina de este modo, todos los bloques finally son ignorados. Ya que no es deseable ignorar los bloques finally es una buena práctica esperar a que todos los threads de trabajo terminen antes de finalizar la aplicación – posiblemente con un timeout (esto puede lograrse utilizando Thread.Join). Si por alguna razón un thread renegado nunca termina, podemos intentar abortarlo, y si esto falla, abandonar el thread permitiendo que muera con el proceso.

Page 42: Uso de threads en C#

• Tener threads en segundo plano puede ser beneficioso, por la razón que es posible que el último diga cuando la aplicación debe terminar. Consideremos la alternativa - un thread en primer plano que no muere - evitando que la aplicación termine. Un thread en primer plano olvidado es particularmente dañino en aplicaciones Windows Form, porque la aplicación aparentará terminar (el menos para el usuario) pero el proceso continuará corriendo.

Page 43: Uso de threads en C#

Preguntas…

• ¿Qué es un proceso y subproceso?

• ¿Qué es un thread?

• ¿Cuál es la diferencia entre estos dos?

• ¿Qué librería se utiliza para poder usar threads?

• ¿Cuáles son algunas de las propiedades de la clase thread?

• ¿Cuándo utilizamos los threads?

• ¿Cuándo no es necesario utilizar threads?

• ¿Qué es multithreading?

• ¿Cuáles son algunos estados y prioridades de los threads?

• Cuando creamos un thread ¿Qué tiempo es asignado para cada hilo?

Page 44: Uso de threads en C#

Gracias por su atención !!!