Veo a mucha gente en publicaciones de blog y aquí en SO evitando o desaconsejando el uso de la Thread
clase en versiones recientes de C # (y me refiero, por supuesto, a 4.0+, con la adición de Task
& friends). Incluso antes, hubo debates sobre el hecho de que la funcionalidad de un hilo antiguo simple puede ser reemplazada en muchos casos por la ThreadPool
clase.
Además, otros mecanismos especializados están haciendo que la Thread
clase sea menos atractiva, como Timer
s reemplazando el combo feo Thread
+ Sleep
, mientras que para las GUI tenemos BackgroundWorker
, etc.
Aún así, Thread
parece seguir siendo un concepto muy familiar para algunas personas (incluido yo mismo), personas que, cuando se enfrentan a una tarea que implica algún tipo de ejecución paralela, saltan directamente al uso de la vieja Thread
clase. Me he estado preguntando últimamente si es hora de enmendar mis caminos.
Entonces, mi pregunta es, ¿hay algún caso en el que sea necesario o útil usar un Thread
objeto antiguo simple en lugar de una de las construcciones anteriores?
fuente
64.5k
. Una presentación bastante impresionanteRespuestas:
La clase Thread no puede quedar obsoleta porque obviamente es un detalle de implementación de todos esos otros patrones que mencionas.
Pero esa no es realmente tu pregunta; tu pregunta es
Por supuesto. Precisamente en aquellos casos en los que una de las construcciones de nivel superior no satisface sus necesidades.
Mi consejo es que si se encuentra en una situación en la que las herramientas de mayor abstracción existentes no satisfacen sus necesidades y desea implementar una solución utilizando subprocesos, entonces debe identificar la abstracción faltante que realmente necesita y luego implementar esa abstracción usando hilos , y luego use la abstracción .
fuente
Los hilos son un bloque de construcción básico para ciertas cosas (a saber, paralelismo y asincronía) y, por lo tanto, no deben eliminarse. Sin embargo , para la mayoría de las personas y la mayoría de los casos de uso, hay cosas más apropiadas para usar que usted mencionó, como los grupos de subprocesos (que brindan una buena forma de manejar muchos trabajos pequeños en paralelo sin sobrecargar la máquina al generar 2000 subprocesos a la vez),
BackgroundWorker
( que encapsula eventos útiles para un solo trabajo de corta duración).Pero el hecho de que en muchos casos sean más apropiados, ya que protegen al programador de reinventar innecesariamente la rueda, cometer errores estúpidos y cosas por el estilo, eso no significa que la clase Thread sea obsoleta. Todavía lo utilizan las abstracciones mencionadas anteriormente y aún lo necesitaría si necesita un control detallado sobre los subprocesos que no está cubierto por las clases más especiales.
En una línea similar,
.NET
no prohíbe el uso de matrices, a pesar deList<T>
ser una mejor opción para muchos casos en los que la gente usa matrices. Simplemente porque es posible que aún desee crear cosas que no están cubiertas por la lib estándar.fuente
Task
yThread
son diferentes abstracciones. Si desea modelar un hilo, laThread
clase sigue siendo la opción más adecuada. Por ejemplo, si necesita interactuar con el hilo actual, no veo mejores tipos para esto.Sin embargo, como señala .NET ha agregado varias abstracciones dedicadas que son preferibles
Thread
en muchos casos.fuente
La
Thread
clase no está obsoleta, sigue siendo útil en circunstancias especiales.Donde trabajo, escribimos un 'procesador en segundo plano' como parte de un sistema de administración de contenido: un servicio de Windows que monitorea directorios, direcciones de correo electrónico y feeds RSS, y cada vez que aparece algo nuevo, ejecuta una tarea en él, generalmente para importar el datos.
Los intentos de usar el grupo de subprocesos para esto no funcionaron: intenta ejecutar demasiadas cosas al mismo tiempo y deshacerse de los discos, así que implementamos nuestro propio sistema de sondeo y ejecución usando directamente la
Thread
clase.fuente
Las nuevas opciones hacen que el uso directo y la gestión de los (costosos) hilos sean menos frecuentes.
Lo cual es una forma muy cara y relativamente compleja de hacer cosas en paralelo.
Tenga en cuenta que el gasto es lo más importante: no puede usar un hilo completo para hacer un trabajo pequeño, sería contraproducente. ThreadPool combate los costos, la clase Task las complejidades (excepciones, espera y cancelación).
fuente
Para responder a la pregunta de " ¿hay algún caso en el que sea necesario o útil utilizar un objeto Thread antiguo y sencillo ", diría que un Thread antiguo sencillo es útil (pero no necesario) cuando tienes un proceso de ejecución prolongado que ganaste? nunca interactuar con desde un hilo diferente.
Por ejemplo, si está escribiendo una aplicación que se suscribe para recibir mensajes de algún tipo de cola de mensajes y su aplicación va a hacer más que solo procesar esos mensajes, entonces sería útil usar un hilo porque el hilo será autónomo (es decir, no está esperando a que se haga) y no es de corta duración. El uso de la clase ThreadPool es más para poner en cola un grupo de elementos de trabajo de corta duración y permitir que la clase ThreadPool administre el procesamiento eficiente de cada uno a medida que hay un nuevo Thread disponible. Las tareas se pueden usar donde usarías Thread directamente, pero en el escenario anterior no creo que te compren mucho. Te ayudan a interactuar con el hilo más fácilmente (lo que no ocurre con el escenario anterior
fuente
System.IO.Threading.Thread
.Probablemente no sea la respuesta que esperaba, pero uso Thread todo el tiempo cuando codifico contra .NET Micro Framework. MF está bastante reducido y no incluye abstracciones de nivel superior y la clase Thread es súper flexible cuando necesita obtener el último rendimiento de una CPU de bajo MHz.
fuente
Puede comparar la clase Thread con ADO.NET. No es la herramienta recomendada para hacer el trabajo, pero no es obsoleta. Otras herramientas se construyen sobre él para facilitar el trabajo.
No está mal usar la clase Thread sobre otras cosas, especialmente si esas cosas no proporcionan la funcionalidad que necesita.
fuente
Definitivamente no es obsoleto.
El problema con las aplicaciones multiproceso es que son muy difíciles de hacer bien (a menudo, el comportamiento indeterminista, la entrada, la salida y también el estado interno es importante), por lo que un programador debe impulsar tanto trabajo como sea posible al marco / herramientas. Resúmalo. Pero el enemigo mortal de la abstracción es el desempeño.
Iría con Threads y bloqueos solo si hubiera problemas de rendimiento graves, objetivos de alto rendimiento.
fuente
Siempre he usado la clase Thread cuando necesito llevar la cuenta y controlar los hilos que he creado. Me doy cuenta de que podría usar el grupo de subprocesos para guardar todo mi trabajo sobresaliente, pero nunca he encontrado una buena manera de realizar un seguimiento de cuánto trabajo se está haciendo actualmente o cuál es el estado.
En cambio, creo una colección y coloco los hilos en ellos después de girarlos; lo último que hace un hilo es quitarse de la colección. De esa manera, siempre puedo saber cuántos subprocesos se están ejecutando y puedo usar la colección para preguntar a cada uno qué está haciendo. Si hay un caso en el que necesito eliminarlos a todos, normalmente tendrías que establecer algún tipo de indicador de "Abortar" en tu aplicación, esperar a que cada hilo se dé cuenta de eso por sí solo y terminen automáticamente; en mi caso, yo puede recorrer la colección y emitir un Thread.Abort a cada uno por turno.
En ese caso, no he encontrado una mejor manera que trabajar directamente con la clase Thread. Como mencionó Eric Lippert, los otros son solo abstracciones de nivel superior, y es apropiado trabajar con las clases de nivel inferior cuando las implementaciones de alto nivel disponibles no satisfacen sus necesidades. Así como a veces necesita hacer llamadas a la API de Win32 cuando .NET no cubre sus necesidades exactas, siempre habrá casos en los que la clase Thread sea la mejor opción a pesar de los "avances" recientes.
fuente