Saltar al contenido

¿El uso de async / await crea un nuevo hilo?

Solución:

En breve NO

De la programación asincrónica con Async y Await: subprocesos

Las palabras clave async y await no provocan la creación de subprocesos adicionales. Los métodos asíncronos no requieren subprocesos múltiples porque un método asíncrono no se ejecuta en su propio subproceso. El método se ejecuta en el contexto de sincronización actual y usa el tiempo en el hilo solo cuando el método está activo. Puede usar Task.Run para mover el trabajo vinculado a la CPU a un subproceso en segundo plano, pero un subproceso en segundo plano no ayuda con un proceso que solo espera que los resultados estén disponibles.

Según MSDN: palabra clave asíncrona

Un método asincrónico se ejecuta sincrónicamente hasta que alcanza su primera expresión de espera, momento en el que el método se suspende hasta que se completa la tarea esperada. Mientras tanto, el control vuelve a quien llama al método, como muestra el ejemplo de la siguiente sección.

Aquí hay un código de muestra para verificarlo:

class Program

{
    static void Main(string[] args)
    {
        Program p = new Program();
        p.Run();
    }

    private void Print(string txt)
    {
        string dateStr = DateTime.Now.ToString("HH:mm:ss.fff");
        Console.WriteLine($"{dateStr} Thread #{Thread.CurrentThread.ManagedThreadId}t{txt}");
    }

    private void Run()
    {
        Print("Program Start");
        Experiment().Wait();
        Print("Program End. Press any key to quit");
        Console.Read();
    }

    private async Task Experiment()
    {
        Print("Experiment code is synchronous before await");
        await Task.Delay(500);
        Print("Experiment code is asynchronous after first await");
    }
}

Y el resultado:
Resultado del experimento: el código después de la espera se ejecuta en otro hilo

Vemos el código del método Experiment () después de que await se ejecuta en otro hilo.

Pero si reemplazo Task.Delay por mi propio código (método SomethingElse):

   class Program
{
    static void Main(string[] args)
    {
        Program p = new Program();
        p.Run();
    }

    private void Print(string txt)
    {
        string dateStr = DateTime.Now.ToString("HH:mm:ss.fff");
        Console.WriteLine($"{dateStr} Thread #{Thread.CurrentThread.ManagedThreadId}t{txt}");
    }

    private void Run()
    {
        Print("Program Start");
        Experiment().Wait();
        Print("Program End. Press any key to quit");
        Console.Read();
    }

    private async Task Experiment()
    {
        Print("Experiment code is synchronous before await");
        await SomethingElse();
        Print("Experiment code is asynchronous after first await");
    }

    private Task SomethingElse()
    {
        Print("Experiment code is asynchronous after first await");
        Thread.Sleep(500);
        return (Task.CompletedTask);
    }
}

¡Noto que el hilo sigue siendo el mismo!

El hilo es el mismo incluso con async / await

En conclusión, diré que el código async / await podría usar otro hilo, pero solo si el hilo es creado por otro código, no por async / await.

En este caso, creo Task.Delay creó el hilo, por lo que puedo concluir que async / await no crea un nuevo hilo como lo dijo @Adriaan Stander.

Perdón por llegar tarde a la fiesta.

Soy nuevo en TPL y me pregunto: ¿Cómo se relaciona el soporte de programación asincrónico que es nuevo en C # 5.0 (a través de las nuevas palabras clave async y await) con la creación de subprocesos?

async/await no se introduce para la creación de subprocesos, sino para utilizar el subproceso actual de manera óptima.

Su aplicación puede leer archivos, esperar la respuesta de otro servidor o incluso realizar un cálculo con un alto acceso a la memoria (simplemente cualquier tarea de E / S). Estas tareas no requieren un uso intensivo de la CPU (cualquier tarea que no utilice el 100% de su hilo).

Piense en que está procesando 1000 tareas no intensivas en CPU. En este caso, el proceso de creación de miles de subprocesos a nivel del sistema operativo podría consumir más CPU y memoria que hacer el trabajo real en un solo subproceso (4 MB por subproceso en Windows, 4 MB * 1000 = 4 GB). Al mismo tiempo, si ejecuta todas las tareas de forma secuencial, es posible que deba esperar hasta que finalicen las tareas de E / S. Que terminan en mucho tiempo para completar la tarea, mientras se mantiene inactiva la CPU.

Dado que necesitamos el parralismo para completar múltiples tareas rápidamente, al mismo tiempo, todas las tareas paralelas no consumen mucha CPU, pero la creación de subprocesos es ineficiente.

El compilador interrumpirá la ejecución en cualquier llamada de método a un async método (independientemente de que sea awaited o no) y ejecutar inmediatamente el código restante, una vez await se alcanza, la ejecución irá dentro de la anterior async. Esto se repetirá una y otra vez hasta que se completen todas las llamadas asincrónicas y su awaiters estan satisfechos.

Si alguno de los métodos asíncronos tiene una gran carga de CPU sin una llamada a un método asíncrono, entonces sí, su sistema dejará de responder y no se llamará a todos los métodos asíncronos restantes hasta que finalice la tarea actual.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *