Diferencias entre tareas y subprocesos [duplicado]

Resuelto Jacek asked hace 11 años • 3 respuestas

Hay dos clases disponibles en .NET: Tasky Thread.

  • ¿Cuál es la diferencia entre esas clases?
  • ¿ Cuándo es mejor utilizar Threadover Task(y viceversa)?
Jacek avatar Nov 17 '12 15:11 Jacek
Aceptado

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

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

  • Task.Delayno necesita ningún tiempo de CPU real; es como configurar un temporizador para que suene en el futuro
  • Una tarea devuelta por WebClient.DownloadStringTaskAsyncno consumirá mucho tiempo de CPU a nivel local; representa un resultado que probablemente pasará la mayor parte de su tiempo en latencia de red o trabajo remoto (en el servidor web)
  • Una tarea devuelta por Task.Run()realmente dice "Quiero que ejecutes este código por separado"; el hilo exacto en el que se ejecuta ese código depende de varios factores.

Tenga en cuenta que la Task<T>abstracción es fundamental para la compatibilidad asíncrona en C# 5.

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

Jon Skeet avatar Nov 17 '2012 09:11 Jon Skeet

Generalmente escuchas que Tarea es un concepto de nivel superior a hilo ... y eso es lo que significa esta frase:

  1. No puede usar Abort/ThreadAbortedException, debe admitir el evento de cancelación en su "código comercial" probando periódicamente el token.IsCancellationRequestedindicador (también evite conexiones largas o sin tiempo de espera, por ejemplo, a la base de datos; de lo contrario, nunca tendrá la oportunidad de probar este indicador). Por la misma razón, Thread.Sleep(delay)la llamada debe reemplazarse con Task.Delay(delay, token)la llamada (pasar el token al interior para tener la posibilidad de interrumpir el retraso).

  2. No hay funcionalidades de subprocesos Suspendni métodos con tareas. La instancia de tarea tampoco se puede reutilizar .Resume

  3. Pero obtienes dos nuevas herramientas:

    a) continuaciones

    // continuation with ContinueWhenAll - execute the delegate, when ALL
    // tasks[] had been finished; other option is ContinueWhenAny
    
    Task.Factory.ContinueWhenAll( 
       tasks,
       () => {
           int answer = tasks[0].Result + tasks[1].Result;
           Console.WriteLine("The answer is {0}", answer);
       }
    );
    

    b) tareas anidadas/secundarias

    //StartNew - starts task immediately, parent ends whith child
    var parent = Task.Factory.StartNew
    (() => {
              var child = Task.Factory.StartNew(() =>
             {
             //...
             });
          },  
          TaskCreationOptions.AttachedToParent
    );
    
  4. Por lo tanto, el subproceso del sistema está completamente oculto a la tarea, pero aún así el código de la tarea se ejecuta en el subproceso concreto del sistema. Los subprocesos del sistema son recursos para las tareas y, por supuesto, todavía hay un grupo de subprocesos bajo el capó de la ejecución paralela de la tarea. Puede haber diferentes estrategias para que los subprocesos ejecuten nuevas tareas. Otro recurso compartido, TaskScheduler, se preocupa por ello. Algunos problemas que resuelve TaskScheduler 1) prefieren ejecutar la tarea y su continuación en el mismo subproceso minimizando el costo de cambio, también conocido como ejecución en línea ) 2) prefieren ejecutar las tareas en el orden en que se iniciaron, también conocido como PreferFairness 3) distribución más efectiva de tareas entre subprocesos inactivos dependiendo del "conocimiento previo de la actividad de las tareas", también conocido como robo de trabajo . Importante: en general, "asíncrono" no es lo mismo que "paralelo". Al jugar con las opciones de TaskScheduler, puede configurar que las tareas asíncronas se ejecuten en un hilo de forma sincrónica. Para expresar la ejecución de código paralelo se podrían utilizar abstracciones superiores (que las Tareas): Parallel.ForEach, PLINQ, Dataflow.

  5. Las tareas están integradas con las funciones async/await de C#, también conocidas como Promise Model , por ejemplo, allí requestButton.Clicked += async (o, e) => ProcessResponce(await client.RequestAsync(e.ResourceName));la ejecución client.RequestAsyncno bloqueará el subproceso de la interfaz de usuario. Importante: bajo el capó, Clickedla llamada delegado es absolutamente regular (todos los subprocesos los realiza el compilador).

Eso es suficiente para tomar una decisión. Si necesita admitir la funcionalidad Cancelar para llamar a una API heredada que tiende a bloquearse (por ejemplo, una conexión sin tiempo de espera) y, en este caso, admite Thread.Abort(), o si está creando cálculos en segundo plano de subprocesos múltiples y desea optimizar el cambio entre subprocesos usando Suspender/Reanudar , eso significa administrar la ejecución paralela manualmente; quédese con Thread. De lo contrario, vaya a Tareas porque le permitirán manipular fácilmente grupos de ellas, están integradas en el lenguaje y hacen que los desarrolladores sean más productivos: Biblioteca paralela de tareas (TPL) .

Roman Pokrovskij avatar Feb 13 '2013 12:02 Roman Pokrovskij