Pregunta

¿Cuál es la diferencia entre usar un hilo nuevo y usar un hilo del grupo de hilos? ¿Qué beneficios de rendimiento existen y por qué debería considerar utilizar un subproceso del grupo en lugar de uno que he creado explícitamente? Estoy pensando específicamente en .NET aquí, pero los ejemplos generales están bien.

¿Fue útil?

Solución

El grupo de subprocesos proporcionará beneficios para operaciones frecuentes y relativamente cortas mediante

  • Reutilizando hilos que ya se han creado en lugar de crear otros nuevos (un proceso costoso)
  • Limita la velocidad de creación de subprocesos cuando hay una ráfaga de solicitudes de nuevos elementos de trabajo (creo que esto solo está en .NET 3.5)

    • Si pone en cola 100 tareas de grupo de subprocesos, solo utilizará tantos subprocesos como los que ya se han creado para atender estas solicitudes (por ejemplo, 10). El grupo de subprocesos realizará comprobaciones frecuentes (creo que cada 500 ms en 3.5 SP1) y si hay tareas en cola, creará un nuevo subproceso. Si sus tareas son rápidas, entonces la cantidad de nuevos subprocesos será pequeña y la reutilización de los 10 o más subprocesos para las tareas cortas será más rápida que la creación de 100 subprocesos por adelantado.

    • Si su carga de trabajo tiene constantemente un gran número de solicitudes de grupo de subprocesos, entonces el grupo de subprocesos se ajustará a su carga de trabajo al crear más subprocesos en el grupo por el proceso anterior para que haya un mayor número de subprocesos disponible para procesar solicitudes

    • marque Aquí para obtener información más detallada sobre cómo funciona el grupo de subprocesos bajo el capó

La creación de un nuevo hilo por sí mismo sería más apropiada si el trabajo fuera relativamente largo (probablemente alrededor de uno o dos segundos, pero depende de la situación específica)

@Krzysztof: los subprocesos de la agrupación de subprocesos son subprocesos de fondo que se detendrán cuando finalice el subproceso principal. Los subprocesos creados manualmente se ponen en primer plano de forma predeterminada (se seguirán ejecutando después de que el subproceso principal haya finalizado), pero se pueden establecer en segundo plano antes de llamar al inicio.

Otros consejos

El grupo de subprocesos administrado .NET: -

  • Los tamaños se basan en la carga de trabajo actual y el hardware disponible
  • Contiene subprocesos de trabajo y subprocesos de puerto de finalización (que se utilizan específicamente para dar servicio a IO)
  • Está optimizado para un gran número de operaciones relativamente de corta duración

Existen otras implementaciones de grupo de subprocesos que podrían ser más adecuadas para operaciones de larga ejecución.

Específicamente, usa un grupo de hilos para evitar que tu aplicación cree demasiados hilos. La característica más importante de un grupo de subprocesos es la cola de trabajo. Es decir, una vez que su máquina esté lo suficientemente ocupada, el conjunto de subprocesos pondrá en cola las solicitudes en lugar de generar inmediatamente más subprocesos.

Entonces, si va a crear un número pequeño y limitado de hilos, créelos usted mismo. Si no puede determinar por adelantado cuántos subprocesos pueden crearse (por ejemplo, se crean en respuesta a la entrada / salida entrante), y su trabajo será de corta duración, use el conjunto de subprocesos. Si no sabe cuántos, pero su trabajo será de larga duración, no hay nada en la plataforma que lo ayude, pero podría encontrar implementaciones alternativas de subprocesos que se ajusten.

también

  

new Thread (). Start ()

genera un subproceso en primer plano que no morirá si cierras tu programa. Las hebras de ThreadPool son hebras de fondo que mueren cuando cierras la aplicación.

Tenía curiosidad por el uso relativo de recursos para estos y ejecuté un punto de referencia en mi computadora portátil Intel i5 dual-core 2012 utilizando la versión .net 4.0 desarrollada en Windows 8. Thread Pools tomó un promedio de 0.035 ms para comenzar donde Threads tomó un Promedio de 5.06ms. En otras palabras, el hilo en la agrupación comenzó aproximadamente 300 veces más rápido para un gran número de hilos de corta duración. Al menos en los subprocesos de rango probado (100-2000), el tiempo total por subproceso parecía bastante constante.

Este es el código que fue evaluado:

    for (int i = 0; i < ThreadCount; i++) {
        Task.Run(() => { });
    }

    for (int i = 0; i < ThreadCount; i++) {
        var t = new Thread(() => { });
        t.Start();
    }

 introduce la descripción de la imagen aquí

Busca aquí un tema anterior:

¿Cuándo no debo usar ThreadPool en .Net?

El resumen es que Threadpool es bueno si necesitas generar muchos subprocesos de corta duración, mientras que el uso de subprocesos te da un poco más de control.

El almacenamiento local de subprocesos no es una buena idea con grupos de subprocesos. Le da a los hilos una " identidad " ;; ya no todos los hilos son iguales Ahora los grupos de subprocesos son especialmente útiles si solo necesita un montón de subprocesos idénticos, listos para hacer su trabajo sin sobrecarga de creación.

Si necesita una gran cantidad de subprocesos, probablemente desee utilizar un ThreadPool. Reutilizan subprocesos, lo que le ahorra la sobrecarga de la creación de subprocesos.

Si solo necesitas un hilo para hacer algo, el hilo es probablemente el más fácil.

La necesidad principal de los subprocesos del grupo de trabajo es manejar pequeñas tareas cortas que se espera que se completen casi al instante. Los controladores de interrupción de hardware a menudo se ejecutan en un contexto de apilamiento que no sería adecuado para un código que no es del kernel, pero un controlador de interrupción de hardware puede descubrir que una devolución de llamada de finalización de E / S en modo usuario debe ejecutarse lo antes posible. Crear un nuevo hilo con el fin de ejecutar tal cosa sería una exageración masiva. Tener muchos subprocesos creados previamente que se pueden enviar para ejecutar devoluciones de llamadas de finalización de E / S u otras cosas similares es mucho más eficiente.

Un aspecto clave de dichos subprocesos es que si los métodos de finalización de E / S siempre se completan esencialmente de forma instantánea y nunca se bloquean, y el número de dichos subprocesos que actualmente ejecutan dichos métodos es al menos igual al número de procesadores, la única forma cualquier otro subproceso podría ejecutarse antes de que uno de los métodos mencionados termine si uno de los otros bloques de métodos o su tiempo de ejecución excede un intervalo de tiempo de subprocesamiento normal; ninguno de estos debería suceder muy a menudo si el grupo de subprocesos se utiliza según lo previsto.

Si no se puede esperar que un método salga dentro de 100 ms o menos cuando comienza la ejecución, el método debe ejecutarse por otros medios que no sean el grupo de subprocesos principal. Si uno tiene que realizar muchas tareas que requieren un uso intensivo de la CPU pero que no se bloquean, puede ser útil enviarlas utilizando un grupo de subprocesos de aplicaciones (uno por núcleo de CPU) que está separado de la " main " conjunto de subprocesos, ya que el uso de más subprocesos que núcleos será contraproducente cuando se ejecuten tareas intensivas de CPU sin bloqueo. Sin embargo, si un método demorará un segundo o más en ejecutarse, y pasará la mayor parte del tiempo bloqueado, es probable que el método se ejecute en un subproceso dedicado y que casi con toda seguridad no se ejecute en un subproceso principal de subprocesos. Si una operación de larga duración necesita ser activada por algo como una devolución de llamada de E / S, uno debe iniciar un subproceso para la operación de larga duración antes de la devolución de llamada y hacer que espere en un monitor en el que la devolución de llamada pulsa, o bien haga que la devolución de llamada inicie un nuevo subproceso para realizar la operación mientras la devolución de llamada finaliza, devolviendo efectivamente su propio subproceso al conjunto de subprocesos.

En general (nunca he usado .NET), un grupo de subprocesos se usaría para fines de administración de recursos. Permite configurar restricciones en su software. También se puede hacer por razones de rendimiento, ya que la creación de nuevos subprocesos puede ser costosa.

También puede haber razones específicas del sistema. En Java (una vez más, no sé si esto se aplica a .NET), el administrador de los subprocesos puede aplicar variables específicas al subproceso a medida que cada subproceso se extrae de la agrupación y desarmarlos cuando se devuelven (una forma común de pasar algo como una identidad).

Ejemplo de restricción: Solo tengo 10 conexiones de db, por lo que solo permitiría 10 subprocesos de trabajo para acceder a la base de datos.

Esto no significa que no debas crear tus propios subprocesos, pero hay condiciones en las que tiene sentido utilizar un grupo.

Usar una agrupación es una buena idea, si no sabes o no puedes controlar cuántos subprocesos se crearán.

Solo tiene un problema con un formulario que usa un hilo para actualizar algún campo de una base de datos en un evento de cambio de posición de un control de lista (evitar la congelación). A mi usuario le tomó 5 minutos tener un error de la base de datos (demasiada conexión con Access) porque estaba cambiando la posición de la lista demasiado rápido ...

Sé que hay otra manera de resolver el problema de la base (incluido no usar el acceso), pero la agrupación es un buen comienzo.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top