¿Cuál es la diferencia entre tarea e hilo?
En C# 4.0, tenemos Task
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) para aprender 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 es posible que con el título de esta pregunta no haya podido obtener la misma. Si alguien sabe sobre el mismo tipo de pregunta publicada aquí anteriormente, por favor proporcione la referencia del enlace.
En términos informáticos, a Task
es un futuro o una promesa . (Algunas personas usan esos dos términos como sinónimos, otras los usan de manera diferente, nadie puede ponerse de acuerdo sobre una definición precisa ). Básicamente, una Task<T>
"promesa" de devolverte un T
, pero no ahora, cariño, estoy un poco ocupado, ¿por qué no? ¿vuelves más tarde?
A Thread
es una forma de cumplir esa promesa. Pero no todo el mundo Task
necesita uno nuevo Thread
. (De hecho, crear un subproceso a menudo no es deseable, porque hacerlo es mucho más costoso que reutilizar un subproceso existente del grupo de subprocesos. Hablaremos más de eso en un momento). Si el valor que está esperando proviene del sistema de archivos o una 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, Task
podrían registrar una devolución de llamada para recibir los valores cuando estén listos.
En particular, Task
no dice por qué se tarda tanto en devolver el valor . Puede ser que lleve mucho tiempo calcularlo o que lleve mucho tiempo recuperarlo. Sólo en el primer caso usarías a Thread
para ejecutar un archivo Task
. (En .NET, los subprocesos son tremendamente caros, por lo que generalmente conviene evitarlos tanto como sea posible y utilizarlos únicamente si desea ejecutar varios cálculos pesados en varias CPU. Por ejemplo, en Windows, un subproceso pesa 12 KiByte ( (Creo que), en Linux, un hilo pesa tan solo 4 KiByte, en Erlang/BEAM incluso solo 400 Byte. ¡En .NET, es 1 MiByte!)
Una tarea es algo que quieres que se haga.
Un hilo es uno de los muchos trabajadores posibles que realiza esa tarea.
En términos de .NET 4.0, una Tarea representa una operación asincrónica. Los subprocesos se utilizan para completar esa operación dividiendo el trabajo en fragmentos y asignándolos a subprocesos separados.
Hilo
Lo básico, probablemente no necesite usarlo, probablemente pueda usar una LongRunning
tarea y aprovechar los beneficios de TPL - Biblioteca paralela de tareas, incluida en .NET Framework 4 (febrero de 2002) y versiones posteriores (también .NET Centro).
Tareas
Abstracción sobre los hilos. Utiliza el grupo de subprocesos (a menos que especifique la tarea como una LongRunning
operación; de ser así, se crea un nuevo subproceso bajo el capó para usted).
Grupo de subprocesos
Como sugiere el nombre: un conjunto de hilos. Este es el marco .NET que maneja una cantidad limitada de subprocesos. ¿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 por usted, reutilizando los subprocesos (sin crearlos ni eliminarlos en cada operación) y ejecutar algunos de ellos en paralelo, de manera que su CPU no se queme.
Vale, pero ¿cuándo utilizar cada uno?
En resumen: utilice siempre tareas.
La tarea es una abstracción, por lo que es mucho más fácil de usar. Le aconsejo que siempre intente utilizar tareas y si se enfrenta a algún problema que le obliga a manejar un hilo usted mismo (probablemente el 1% de las veces), utilice hilos.
PERO tenga en cuenta que:
- Vinculado a E/S : para operaciones vinculadas a E/S (llamadas a bases de datos, archivos de lectura/escritura, llamadas a API, etc.), evite el uso de tareas normales, utilice
LongRunning
tareas ( o subprocesos si es necesario ). Porque el uso de tareas lo llevaría a un grupo de subprocesos con algunos subprocesos ocupados y muchas otras tareas esperando su turno para ocupar el grupo. - Vinculado a la CPU : para operaciones vinculadas a la CPU, simplemente 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:
- Una tarea es por defecto una tarea en segundo plano. No puedes tener una tarea en primer plano. Por otro lado, un hilo puede estar en segundo plano o en primer plano (use la propiedad IsBackground para cambiar el comportamiento).
- Las tareas creadas en el grupo de subprocesos reciclan los subprocesos, lo que ayuda a ahorrar recursos. Por lo tanto, en la mayoría de los casos, las tareas deberían ser su opción predeterminada.
- Si las operaciones son rápidas, es mucho mejor utilizar una tarea en lugar de un hilo. Para operaciones de larga duración, las tareas no ofrecen muchas ventajas sobre los subprocesos.