Tutorial: Usar el depurador con métodos asincrónicos

Mediante la característica de Async, puede llamar a métodos asincrónicos sin usar devoluciones o dividir el código a través de varios métodos o de expresiones lambda. Para crear asincrónico sincrónico de código, se llama a un método asincrónico en lugar de un método sincrónico y agrega algunas palabras clave al código. Para obtener más información, vea Programación asincrónica con Async y Await (C# y Visual Basic).

En el depurador de Visual Studio, puede utilizar Paso a paso por instrucciones, Paso a paso por procedimientos, y los comandos Paso a paso para salir con la característica de Async . También puede seguir utilizando los puntos de interrupción, ver determinado el flujo de control en una instrucción que contenga un operador aguardar. En este tutorial, se realizarán las siguientes, que se pueden ejecutar en cualquier orden.

  • Muestra el flujo de control en una instrucción de aguardar con los puntos de interrupción.

  • Comprender el comportamiento de los comandos Paso a paso por instrucciones y Paso a paso por procedimientos de las instrucciones que contienen un operador aguardar.

  • Comprender el comportamiento del comando Paso a paso para salir cuando se utiliza dentro de un método async.

Puntos de interrupción para mostrar el flujo de control

Si marca un método con el modificador de Async (Visual Basic) o de async (C#), puede utilizar el operador de Espera (Visual Basic) o de espera (C#) en el método. Para crear una expresión de aguardar, asociará el operador aguardar a una tarea. Cuando una expresión de aguardar se denomina para la tarea, el método actual sale inmediatamente y devuelve otra tarea. Cuando la tarea que está asociado el operador aguardar finaliza, la ejecución se reanuda en el mismo método. Para obtener más información, vea Flujo de control en programas asincrónicos (C# y Visual Basic).

Nota

Un método async vuelve al llamador cuando cualquiera que encuentra el primer objeto aguardado que aún no se completa o alcanza el final del método async, lo que ocurre primero.

Nota

Las aplicaciones de consola en estos ejemplos utilizan el método de Wait para evitar que la aplicación finalice en Main.No debe utilizar el método de Wait fuera de aplicaciones de consola porque una situación de interbloqueo puede aparecer.

Los puntos de interrupción siguientes de los conjuntos de procedimiento para mostrar qué ocurre cuando la aplicación sea una instrucción de aguardar. También puede mostrar el flujo de control agregando las instrucciones de Debug.WriteLine .

  1. Cree una aplicación de consola y, a continuación pegue el siguiente código en él:

    ' Breakpoints to show control flow.
    Imports System.Threading.Tasks
    
    Module Module1
        Sub Main()
            Dim theTask = ProcessAsync()
            Dim x = 0 ' set breakpoint
            theTask.Wait()
        End Sub
    
        Async Function ProcessAsync() As Task
            Dim result = Await DoSomethingAsync()  ' set breakpoint
    
            Dim y = 0 ' set breakpoint
        End Function
    
        Async Function DoSomethingAsync() As Task(Of Integer)
            Await Task.Delay(1000)
            Return 5
        End Function
    End Module
    
    // Breakpoints to show control flow.
    using System.Threading.Tasks;
    
    class Program
    {
        static void Main(string[] args)
        {
            Task theTask = ProcessAsync();
            int x = 0;  // set breakpoint
            theTask.Wait();
        }
    
        static async Task ProcessAsync()
        {
            var result = await DoSomethingAsync();  // set breakpoint
    
            int y = 0;  // set breakpoint
        }
    
        static async Task<int> DoSomethingAsync()
        {
            await Task.Delay(1000);
            return 5;
        }
    }
    
  2. Establezca puntos de interrupción de depuración en las tres líneas que finalizan con un comentario del “punto de interrupción establecido”.

  3. Elija la tecla F5, o elija Depurar, Iniciar depuración en la barra de menús para ejecutar la aplicación.

    La aplicación entra en el método y las interrupciones de ProcessAsync en la línea que contiene el operador aguardar.

  4. Elija la tecla F5 de nuevo.

    Dado que la aplicación detenido en una instrucción que contenga un operador aguardar, la aplicación cierra inmediatamente el método async y devuelve una tarea. Por tanto, la aplicación finaliza el método y las interrupciones de ProcessAsync en el punto de interrupción en el método de llamada (Main).

  5. Elija la tecla F5 de nuevo.

    Cuando el método de DoSomethingAsync completa, el código reanuda después de la instrucción de aguardar en el método de llamada. Por consiguiente, la aplicación se interrumpe en el punto de interrupción en el método de ProcessAsync .

    Cuando DoSomethingAsync se aguardado inicialmente, el método de ProcessAsync fue y devolvió una tarea. Cuando el método aguardado de DoSomethingAsync a completo, la evaluación de la instrucción de aguardar generó el valor devuelto de DoSomethingAsync. El método de DoSomethingAsync se define para devolver Task (Of Integer) en Visual Basic o Task<int> en C#, por lo que el valor en la instrucción return es un entero. Para obtener más información, vea Tipos de valor devuelto de Async (C y Visual Basic).

JJ155813.collapse_all(es-es,VS.110).gifObtener y después esperando una tarea

En el método de ProcessAsync , la instrucción Dim result = Await DoSomethingAsync() (Visual Basic) o var result = await DoSomethingAsync(); (C#) es una contracción de las dos instrucciones siguientes:

Dim theTask = DoSomethingAsync()
Dim result = Await theTask
var theTask = DoSomethingAsync();
var result = await theTask;

La primera línea de código llama al método async y devuelve una tarea. Esa tarea se asocia el operador aguardar en la línea de código siguiente. Los resultados de la instrucción de aguardar el método (ProcessAsync) y devuelven otra tarea. Cuando finaliza la tarea que está asociado el operador aguardar, el código se reanuda en el método (ProcessAsync) después de la instrucción de aguardar.

Cuando la instrucción de aguardar inmediatamente devuelve otra tarea, esa tarea es el argumento devuelto del método async que contiene el operador aguardar (ProcessAsync). La tarea devuelta por el aguardar incluye la ejecución del código que produce después de que el aguardar en el mismo método, por esa tarea es diferente de la tarea que se asocia el aguardar.

Ejecutar y paso Compilaciones

El comando Paso a paso por instrucciones de un método, pero el comando Paso a paso por procedimientos ejecuta la llamada al método y después se interrumpe en la línea siguiente del método de llamada. Para obtener más información, vea [NIB] Información general sobre cómo ejecutar código.

El procedimiento siguiente muestra lo que ocurre cuando se elige los comandos Paso a paso por instrucciones o Paso a paso por procedimientos en una instrucción de aguardar.

  1. Reemplace el código de la aplicación de consola con el código siguiente.

    ' Step Into and Step Over Example
    Imports System.Threading.Tasks
    
    Module Module1
        Sub Main()
            ProcessAsync.Wait()
        End Sub
    
        Async Function ProcessAsync() As Task
            Dim result = Await DoSomethingAsync()  ' Step Into or Step Over from here
    
            Dim y = 0
        End Function
    
        Async Function DoSomethingAsync() As Task(Of Integer)
            Await Task.Delay(1000)
            Return 5
        End Function
    End Module
    
    // Step Into and Step Over Example.
    using System.Threading.Tasks;
    
    class Program
    {
        static void Main(string[] args)
        {
            ProcessAsync().Wait();
        }
    
        static async Task ProcessAsync()
        {
            var result = await DoSomethingAsync();  // Step Into or Step Over from here
    
            int y = 0;
        }
    
        static async Task<int> DoSomethingAsync()
        {
            await Task.Delay(1000);
            return 5;
        }
    }
    
  2. Elija la F11, o elija Depurar, Paso a paso por instrucciones de la barra de menús para iniciar una demostración de comando de Step Into en una instrucción que contenga un operador aguardar.

    La aplicación se inicia y se interrumpe en la primera línea, que es Sub Main() en Visual Basic o la llave de apertura del método de Main en C#.

  3. Elija la F11 tres veces más.

    La aplicación ahora debe estar en la instrucción de aguardar en el método de ProcessAsync .

  4. Elija la F11.

    La aplicación entra en el método y las interrupciones de DoSomethingAsync en la primera línea. Este comportamiento se produce aunque, en la instrucción de await , la aplicación inmediatamente vuelve al método de llamada (Main).

  5. Mantenga elegir la F11 hasta que la aplicación vuelva a la instrucción de aguardar en el método de ProcessAsync .

  6. Elija la F11.

    La aplicación se interrumpe en la línea que sigue a la instrucción de aguardar.

  7. En la barra de menú, elija Depurar, Detener depuración para detener la ejecución de la aplicación.

    Los pasos siguientes muestran el comando Paso a paso por procedimientos en una instrucción de aguardar.

  8. Elija la F11 cuatro veces, o elija Depurar, Paso a paso por instrucciones de la barra de menús cuatro veces.

    La aplicación ahora debe estar en la instrucción de aguardar en el método de ProcessAsync .

  9. Elija la F10, o elija Depurar, Paso a paso por procedimientos en la barra de menús.

    La ejecución se interrumpe en la línea que sigue a la instrucción de aguardar. Este comportamiento se produce aunque la aplicación vuelve inmediatamente al método de llamada (Main) en la instrucción de aguardar. De Step Over de comando los pasos también sobre la ejecución del método de DoSomethingAsync , tal y como se esperaba.

  10. En la barra de menú, elija Depurar, Detener depuración para detener la ejecución de la aplicación.

    Aunque los pasos siguientes muestran, el comportamiento de los comandos Paso a paso por instrucciones y Paso a paso por procedimientos difiere ligeramente cuando el operador aguardar está en otra línea de la llamada al método async.

  11. En el método de ProcessAsync , reemplace la instrucción de aguardar con el código siguiente. El original espera la instrucción es una contracción de las dos instrucciones siguientes.

    Dim theTask = DoSomethingAsync()
    Dim result = Await theTask
    
    var theTask = DoSomethingAsync();
    var result = await theTask;
    
  12. Elija la F11 o elija Depurar, Paso a paso por instrucciones de varias veces la barra de menús para iniciar la ejecución y recorrer el código.

    En la llamada a DoSomethingAsync, las interrupciones del comando Paso a paso por instrucciones del método de DoSomethingAsync , mientras que el comando Paso a paso por procedimientos va a la siguiente instrucción, según lo esperado. En la instrucción de aguardar, interrupción de ambos comandos en la instrucción que sigue al aguardar.

Paso a paso para salir

En los métodos que no son async, el comando Paso a paso para salir adapta el método de llamada en el código que realiza la llamada al método. Para los métodos async, para donde más complejas se interrumpa la ejecución en el método de llamada, y esa lógica depende de si el comando Paso a paso para salir es la primera línea del método async.

  1. Reemplace el código de la aplicación de consola con el código siguiente.

    ' Step Out Example
    Imports System.Threading.Tasks
    
    Module Module1
        Sub Main()
            ProcessAsync.Wait()
        End Sub
    
        Async Function ProcessAsync() As Task
            Dim theTask = DoSomethingAsync()
            Dim z = 0
            Dim result = Await theTask
        End Function
    
        Async Function DoSomethingAsync() As Task(Of Integer)
            Debug.WriteLine("before")  ' Step Out from here
            Await Task.Delay(1000)
            Debug.WriteLine("after")
            Return 5
        End Function
    End Module
    
    // Step Out Example.
    using System.Diagnostics;
    using System.Threading.Tasks;
    
    class Program
    {
        static void Main(string[] args)
        {
            ProcessAsync().Wait();
        }
    
        static async Task ProcessAsync()
        {
            var theTask = DoSomethingAsync();
            int z = 0;
            var result = await theTask;
        }
    
        static async Task<int> DoSomethingAsync()
        {
            Debug.WriteLine("before");  // Step Out from here
            await Task.Delay(1000);
            Debug.WriteLine("after");
            return 5;
        }
    }
    
  2. Establezca un punto de interrupción en la línea de Debug.WriteLine("before") en el método de DoSomethingAsync .

    Éste es mostrar el comportamiento del comando Paso a paso para salir de una línea en un método async que no sea la primera línea.

  3. Elija la tecla F5 o elija Depurar, Iniciar depuración en la barra de menús para iniciar la aplicación.

    El código se interrumpe en Debug.WriteLine("before") en el método de DoSomethingAsync .

  4. Elija las teclas mayús+f11, o elija Depurar, Paso a paso para salir de la barra de menús.

    La aplicación se interrumpe en el método de llamada en la instrucción de aguardar para la tarea que se asocia el método actual. Como resultado, la aplicación se interrumpe en la instrucción de aguardar en el método de ProcessAsync . La aplicación no penetra en Dim z = 0 (Visual Basic) o int z = 0; (C#), que es el código que realiza la llamada al método de DoSomethingAsync .

  5. Elija Depurar, Detener depuración en la barra de menús para detener la ejecución de la aplicación.

    Los pasos siguientes se muestra lo que sucede cuando se Paso a paso para salir de la primera línea de un método async.

  6. Quite el punto de interrupción existente, y agregue un punto de interrupción en la primera línea del método de DoSomethingAsync .

    En C#, agregue el punto de interrupción en la llave de apertura del método de DoSomethingAsync . En Visual Basic, agregue el punto de interrupción en la línea que contiene Async Function DoSomethingAsync() As Task(Of Integer).

  7. Elija la tecla F5 para iniciar la aplicación.

    El código se interrumpe en la primera línea del método de DoSomethingAsync .

  8. En la barra de menú, elija Depurar, Ventanas, Resultados.

    Se abre la ventana Resultados.

  9. Elija las teclas mayús+f11, o elija Depurar, Paso a paso para salir de la barra de menús.

    La aplicación reanuda hasta que el método async alcanza su primer espera y, a continuación la aplicación se interrumpe en la instrucción de llamada. Como resultado, la aplicación se interrumpe en Dim the Task = DoSomethingAsync() (Visual Basic) o var theTask = DoSomethingAsync(); (C#). “Antes de que el mensaje ha producido en la ventana de salida, pero “después de” no se ha producido el mensaje todavía.

  10. Elija la tecla F5 para continuar la ejecución de la aplicación.

    La aplicación continúa con la instrucción que sigue a la instrucción de aguardar en la función llamada async (DoSomethingAsync). “A” de mensaje en la ventana de salida.

Vea también

Conceptos

[NIB] Información general sobre cómo ejecutar código