tiempo thread tareas multihilos mismo metodos hilos ejecutar c# multithreading c#-4.0 task-parallel-library

thread - tareas en c#



¿Cuál es la diferencia entre tarea y hilo? (8)

En C # 4.0, tenemos Task en el espacio de nombres System.Threading.Tasks . ¿Cuál es la verdadera diferencia entre Thread y Task ? Hice un programa de muestra (ayuda tomada de MSDN) por mi propio aprendizaje con

Parallel.Invoke Parallel.For Parallel.ForEach

Pero tengo muchas dudas ya que la idea no es tan clara.

Inicialmente busqué en Stackoverflow un tipo de pregunta similar, pero con el título de esta pregunta no pude obtener la misma. Si alguien sabe sobre el mismo tipo de pregunta que se publicó aquí anteriormente, por favor proporcione la referencia del enlace.


Hilo

Lo esencial es que probablemente no necesite usarlo, probablemente pueda usar una tarea LongRunning y aprovechar los beneficios de TPL - Task Parallel Library, incluido en .NET Framework 4 (febrero de 2002) y superior (también. NET Core).

Tareas

Abstracción por encima de los hilos. Utiliza el grupo de subprocesos (a menos que especifique la tarea como una operación LongRunning , si es así, se creará un nuevo subproceso bajo el capó para usted).

Grupo de hilo

Como su nombre indica: un conjunto de hilos. Es .NET Framework el manejo de un número limitado de subprocesos para usted. ¿Por qué? Porque abrir 100 subprocesos para ejecutar costosas operaciones de CPU en un procesador con solo 8 núcleos definitivamente no es una buena idea. El marco mantendrá este grupo para usted, reutilizando los subprocesos (no los creará / eliminará en cada operación) y ejecutará algunos de ellos en paralelo, de manera que su CPU no se queme.

OK, pero cuando usar cada uno?

En resumen: usar siempre las tareas.

La tarea es una abstracción, por lo que es mucho más fácil de usar. Le aconsejo que siempre intente usar tareas y si se enfrenta a algún problema que lo obligue a manejar un hilo por sí mismo (probablemente el 1% del tiempo), entonces use hilos.

PERO tenga en cuenta que:

  • Límite de E / S : para las operaciones de E / S enlazadas (llamadas de base de datos, archivos de lectura / escritura, llamadas de API, etc.) evite el uso de tareas normales, use tareas LongRunning ( o hilos si es necesario ). Debido a que el uso de tareas lo llevaría a un grupo de subprocesos con algunos subprocesos ocupados y muchas otras tareas esperando su turno para tomar el grupo.
  • CPU Bound : para operaciones enlazadas de CPU, solo use las tareas normales (que internamente usarán el grupo de subprocesos) y sea feliz.

Además de los puntos anteriores, sería bueno saber que:

  1. Una tarea es por defecto una tarea en segundo plano. No puedes tener una tarea de primer plano. Por otro lado, un hilo puede ser de fondo o en primer plano (use la propiedad IsBackground para cambiar el comportamiento).
  2. Las tareas creadas en el grupo de subprocesos reciclan los subprocesos que ayudan a ahorrar recursos. Por lo tanto, en la mayoría de los casos, las tareas deben ser su opción predeterminada.
  3. Si las operaciones son rápidas, es mucho mejor usar una tarea en lugar de un hilo. Para operaciones de larga ejecución, las tareas no proporcionan muchas ventajas sobre los subprocesos.

Cuando ejecutamos cosas en varios subprocesos, no se garantiza que los subprocesos estén separados entre varios procesadores.

Task es un objeto liviano para administrar una unidad de trabajo paralelizable. Se puede usar cuando quieras ejecutar algo en paralelo. Paralelo significa que el trabajo se distribuye en varios procesadores para maximizar la velocidad de cómputo. Las tareas están ajustadas para aprovechar los procesadores multicores.

La tarea proporciona las siguientes funciones poderosas sobre el hilo.

  • Si el sistema tiene varias tareas, entonces hace uso del grupo de subprocesos CLR internamente y, por lo tanto, no tiene la sobrecarga asociada con la creación de un subproceso dedicado utilizando el subproceso. También reduce el tiempo de cambio de contexto entre múltiples hilos.
  • La tarea puede devolver un resultado. No hay un mecanismo directo para devolver el resultado desde el hilo.
  • Espere en un conjunto de tareas, sin una construcción de señalización.

  • Podemos encadenar tareas para ejecutar una tras otra.

  • Establezca una relación padre / hijo cuando una tarea se inicia desde otra tarea.

  • La excepción de tarea secundaria puede propagarse a la tarea principal.

  • Tarea de soporte de cancelación mediante el uso de tokens de cancelación.

  • La implementación asíncrona es fácil en las tareas, utilizando las palabras clave ''async'' y ''espere''.


En términos informáticos, una Task es un futuro o una promesa . (Algunas personas usan esos dos términos sinónimo, otros los usan de manera diferente, nadie puede estar de acuerdo con una definición precisa ). Básicamente, una Task<T> "promete" devolverte una T , pero no ahora, cariño, estoy un poco ocupado , ¿por qué no vuelves más tarde?

Un Thread es una forma de cumplir esa promesa. Pero no todas las Task necesitan un Thread nuevo. (De hecho, la creación de un hilo a menudo no es deseable, ya que hacerlo es mucho más costoso que reutilizar un hilo existente de la agrupación de hilos. Más sobre eso en un momento). Si el valor que está esperando proviene del sistema de archivos o La base de datos o la red, entonces no hay necesidad de que un hilo se siente y espere los datos cuando puede atender otras solicitudes. En su lugar, la Task podría registrar una devolución de llamada para recibir el (los) valor (es) cuando estén listos.

En particular, la Task no dice por qué es que lleva tanto tiempo devolver el valor. Puede ser que demore mucho tiempo en calcularse o que demore mucho tiempo en procesarse. Solo en el primer caso utilizarías un Thread para ejecutar una Task . (En .NET, los subprocesos son extremadamente caros, por lo que generalmente querrá evitarlos lo más posible y realmente solo usarlos si quiere ejecutar múltiples cálculos pesados ​​en múltiples CPUs. Por ejemplo, en Windows, un subproceso pesa 12 KiByte ( Pienso), en Linux, un hilo pesa tan poco como 4 KiByte, en Erlang / BEAM incluso de solo 400 bytes. En .NET, ¡es 1 MiByte!


La tarea es como una operación que desea realizar, Thread ayuda a administrar esas operaciones a través de múltiples nodos de proceso. La tarea es una opción liviana, ya que el subprocesamiento puede llevar a una gestión de código compleja.
Sugeriré leer de MSDN (Best in world) siempre

Task

Thread


Puede usar la Task para especificar lo que desea hacer y luego adjuntar esa Task con un Thread . de modo que la Task se ejecutaría en ese Thread recién creado en lugar de en el subproceso de la GUI.

Utilice la Task con TaskFactory.StartNew(Action action) . Aquí ejecutas un delegado, así que si no usas ningún hilo, se ejecutará en el mismo hilo (hilo GUI). Si menciona un hilo, puede ejecutar esta Task en un hilo diferente. Este es un trabajo innecesario porque puede ejecutar directamente el delegado o adjuntar ese delegado a un hilo y ejecutar ese delegado en ese hilo. Así que no lo uses. es simplemente innecesario Si pretende optimizar su software, este es un buen candidato para ser eliminado.

** Tenga en cuenta que la Action es un delegate .


Una tarea es algo que quieres hacer.

Un hilo es uno de los muchos trabajadores posibles que realiza esa tarea.

En términos de .NET 4.0, una Task representa una operación asíncrona. Los hilos se utilizan para completar esa operación al dividir el trabajo en trozos y asignarlos a hilos separados.


Usualmente utilizo Task para interactuar con Winforms y un simple background background para que no se congele la interfaz de usuario. Aquí un ejemplo cuando prefiero usar Task

private async void buttonDownload_Click(object sender, EventArgs e) { buttonDownload.Enabled = false; await Task.Run(() => { using (var client = new WebClient()) { client.DownloadFile("http://example.com/file.mpeg", "file.mpeg"); } }) buttonDownload.Enabled = true; }

VS

private void buttonDownload_Click(object sender, EventArgs e) { buttonDownload.Enabled = false; Thread t = new Thread(() => { using (var client = new WebClient()) { client.DownloadFile("http://example.com/file.mpeg", "file.mpeg"); } this.Invoke((MethodInvoker)delegate() { buttonDownload.Enabled = true; }); }); t.IsBackground = true; t.Start(); }

La diferencia es que no necesitas usar MethodInvoker y un código más corto.