Diferencias entre tareas y subprocesos [duplicar]


Esta pregunta ya tiene una respuesta aquí:

Soy nuevo en la programación paralela. Hay dos clases disponibles en. NET: Task y Thread.

Entonces, la pregunta es: ¿Cuál es la diferencia entre esas clases? ¿Cuándo es mejor usar Thread y cuándo Task?

Author: Yves M., 2012-11-17

4 answers

Thread es un concepto de nivel inferior: si estás iniciando directamente un subproceso, sabes que será un subproceso separado, en lugar de ejecutarse en el grupo de subprocesos, etc.

Task es más que solo una abstracción de" dónde ejecutar algún código", sin embargo, es realmente solo"la promesa de un resultado en el futuro". Así como algunos ejemplos diferentes:

  • Task.Delay no necesita tiempo de CPU real; es como configurar un temporizador para que se apague en el futuro
  • Una tarea devuelta por WebClient.DownloadStringTaskAsync no tomará mucho tiempo de CPU localmente; representa un resultado que es probable que pase la mayor parte de su tiempo en latencia de red o trabajo remoto (en el servidor web)
  • Una tarea devuelta por Task.Run() realmente es diciendo "Quiero que ejecutes este código por separado"; el hilo exacto en el que se ejecuta ese código depende de una serie de factores.

Tenga en cuenta que la abstracción Task<T> es fundamental para el soporte asincrónico en C# 5.

En general, le recomiendo que utilice el abstracción de mayor nivel siempre que pueda: en el código C# moderno rara vez debería necesitar iniciar explícitamente su propio subproceso.

 346
Author: Jon Skeet,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-11-17 09:03:57

Fuente

Thread

Thread representa un subproceso real a nivel del sistema operativo, con su propia pila y recursos del núcleo. (técnicamente, una implementación de CLR podría usar fibras en su lugar, pero ningún CLR existente hace esto) Thread permite el mayor grado de control; puede Abortar () o Suspender() o Reanudar () un hilo (aunque esto es una muy mala idea), puede observar su estado y puede establecer propiedades a nivel de hilo como el tamaño de la pila, cultura.

El problema con el subproceso es que los subprocesos del sistema operativo son costosos. Cada subproceso que tiene consume una cantidad no trivial de memoria para su pila, y agrega sobrecarga de CPU adicional a medida que el procesador cambia de contexto entre subprocesos. En su lugar, es mejor tener un pequeño grupo de subprocesos que ejecuten su código a medida que el trabajo esté disponible.

Hay momentos en que no hay Hilo alternativo. Si necesita especificar el nombre (para fines de depuración) o el estado del apartamento (para mostrar una interfaz de usuario), debe crear su propio hilo (tenga en cuenta que tener varios hilos de interfaz de usuario es generalmente una mala idea). Además, si desea mantener un objeto que es propiedad de un único subproceso y solo puede ser utilizado por ese subproceso, es mucho más fácil crear explícitamente una instancia de subproceso para que pueda verificar fácilmente si el código que intenta usarlo se está ejecutando en el subproceso correcto.

ThreadPool

ThreadPool es una envoltura alrededor de un grupo de hilos mantenidos por el CLR. ThreadPool no te da control en absoluto; puede enviar trabajo para ejecutar en algún momento, y puede controlar el tamaño del grupo, pero no puede establecer nada más. Ni siquiera se puede decir cuándo el grupo comenzará a ejecutar el trabajo que le envíe.

El uso de ThreadPool evita la sobrecarga de crear demasiados hilos. Sin embargo, si envía demasiadas tareas de larga duración al threadpool, puede llenarse, y el trabajo posterior que envíe puede terminar esperando que terminen los elementos de larga duración anteriores. In addition, the ThreadPool no ofrece ninguna forma de averiguar cuándo se ha completado un elemento de trabajo (a diferencia de Thread.Join ()), ni una forma de obtener el resultado. Por lo tanto, ThreadPool se usa mejor para operaciones cortas donde la persona que llama no necesita el resultado.

Tarea

Finalmente, la clase Task de la Biblioteca Task Parallel ofrece lo mejor de ambos mundos. Al igual que el ThreadPool, una tarea no crea su propio subproceso del sistema operativo. En su lugar, las tareas son ejecutadas por un TaskScheduler; el scheduler predeterminado simplemente se ejecuta en el ThreadPool.

A diferencia de ThreadPool, Task también le permite averiguar cuándo termina y (a través de la Tarea genérica) devolver un resultado. Puedes llamar a ContinueWith () en una tarea existente para que ejecute más código una vez que la tarea termine (si ya ha terminado, ejecutará la devolución de llamada inmediatamente). Si la tarea es genérica, ContinueWith () te pasará el resultado de la tarea, permitiéndote ejecutar más código que la use.

También puede esperar sincrónicamente a que una tarea termine llamar a Wait () (o, para una tarea genérica, obteniendo la propiedad Result). Como Hilo.Join(), esto bloqueará el subproceso invocador hasta que la tarea termine. Esperar sincrónicamente por una tarea suele ser una mala idea; evita que el subproceso de llamada haga cualquier otro trabajo, y también puede conducir a bloqueos si la tarea termina esperando (incluso asincrónicamente) por el subproceso actual.

Dado que las tareas todavía se ejecutan en el ThreadPool, no deben usarse para operaciones de larga duración, ya que aún pueden llene el grupo de hilos y bloquee el trabajo nuevo. En su lugar, Task proporciona una opción LongRunning, que le dirá al TaskScheduler que haga girar un nuevo hilo en lugar de ejecutarse en el ThreadPool.

Todas las API de concurrencia de alto nivel más recientes, incluido el Parallel.Para los métodos * (), PLINQ, C# 5 await y los métodos asincrónicos modernos en BCL, todos están construidos en Task.

Conclusión

La conclusión es que la tarea es casi siempre la mejor opción; proporciona una API mucho más potente y evita desperdiciar hilos del sistema operativo.

Las únicas razones para crear explícitamente sus propios subprocesos en código moderno son establecer opciones por subproceso o mantener un subproceso persistente que necesita mantener su propia identidad.

 210
Author: M_ Fa,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-07-13 11:22:46

Task es un concepto de nivel más alto que thread ... y eso es lo que esta frase significa :

  1. No se puede utilizar Abort / ThreadAbortedException, usted debe apoyar cancelar evento en su "código de negocio" probando periódicamente la bandera token.IsCancellationRequested (también evite conexiones largas o sin tiempo, por ejemplo, a la base de datos, de lo contrario nunca tendrá la oportunidad de probar esta bandera). Por la misma razón Thread.Sleep(delay) debe sustituirse por Task.Delay(delay, token);

  2. No hay hilos Suspend () y Resume() funcionalidad de métodos con tareas. Instancia de la tarea no se puede reutilizar tampoco.

  3. Pero obtienes dos nuevas herramientas: continuaciones, y tareas anidadas/secundarias ; esas dos muestras demuestran la idea y la sintaxis:

      // continuation - execute the delegate, when all tasks[] had been finished
    Task.Factory.ContinueWhenAll(
    tasks,
    () =>
       {
           int answer = tasks[0].Result + tasks[1].Result;
           Console.WriteLine("The answer is {0}", answer);
       }
    );
    
    
    //StartNew - starts task immediately, parent ends whith child
    var parent = Task.Factory.StartNew
    (() => {
              var child = Task.Factory.StartNew(() =>
             {
             //...
             });
          },  
          TaskCreationOptions.AttachedToParent
    );
    
  4. Así que el hilo del sistema está completamente oculto de la tarea, pero aún así el código de la tarea se ejecuta en el hilo del sistema concreto. Los subprocesos del sistema son recursos para tareas y, por supuesto, todavía hay un grupo de subprocesos bajo el ejecución paralela de tareas. Puede haber diferentes estrategias de cómo thread obtener nuevas tareas para ejecutar. Otro recurso compartido TaskScheduler se preocupa por él. Algunos problemas que TaskScheduler resuelve 1) prefieren ejecutar la tarea y su conexión en el mismo subproceso minimizando el costo de conmutación-aka ejecución en línea ) 2) prefieren ejecutar las tareas en un orden en que se iniciaron-aka Preferencia 3) distribución más efectiva de las tareas entre subprocesos inactivos dependiendo de" conocimiento previo de la actividad de tareas " - también conocido como Robo de trabajo. Importante: en general "async "no es lo mismo que"parallel". Jugando con las opciones de TaskScheduler puede configurar las tareas asíncronas para que se ejecuten en un hilo de forma sincrónica.

  5. Las tareas están integradas con las características async/await de C# aka Promise Model, por ejemplo, allí requestButton.Clicked += async (o, e) => ProcessResponce(await client.RequestAsync(e.ResourceName)); la ejecución de client.RequestAsync no bloqueará el subproceso de la interfaz de usuario. Importante: bajo el capó Clicked la llamada de delegado es absolutamente regular (todo el subproceso es hecho por el compilador).

Eso es suficiente para hacer una elección. Si necesita admitir la funcionalidad Cancelar de llamar a la API heredada que tiende a colgarse (por ejemplo, conexión sime timeoutless) y para este caso admite Thread.Abort(), o si está creando cálculos en segundo plano de varios subprocesos y desea optimizar la conmutación entre subprocesos usando Suspender/Reanudar, eso significa administrar la ejecución paralela manualmente - permanecer con Subprocesos. De lo contrario ir a las tareas debido a que le dará fácil manipular en grupos de ellos y se integran en el lenguaje.

 27
Author: Roman Pokrovskij,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-09-21 18:02:14

El Thread la clase se usa para crear y manipular un subproceso en Windows.

A Task representa alguna operación asíncrona y es parte de la Biblioteca de Tareas Paralelas, un conjunto de API para ejecutar tareas de forma asíncrona y en paralelo.

En los días de antaño (es decir, antes de TPL) solía ser que el uso de la clase Thread era una de las formas estándar de ejecutar código en segundo plano o en paralelo (una mejor alternativa era a menudo el uso de una ThreadPool), sin embargo, esto era engorroso y tenía varias desventajas, no menos importante de las cuales era la sobrecarga de rendimiento de crear un hilo completamente nuevo para realizar una tarea en segundo plano.

Hoy en día el uso de tareas y el TPL es una solución mucho mejor el 90% del tiempo, ya que proporciona abstracciones que permite un uso mucho más eficiente de los recursos del sistema. Imagino que hay algunos escenarios en los que desea un control explícito sobre el hilo en el que está ejecutando su código, sin embargo en términos generales, si desea ejecutar algo asincrónicamente, su primer puerto de llamada debe ser el TPL.

 26
Author: Justin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-03-27 19:12:45