Nota
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
Visual Studio proporciona varias herramientas y elementos de interfaz de usuario para ayudarle a depurar aplicaciones multiproceso. En este tutorial se muestra cómo usar marcadores de subprocesos, la ventanas Pilas paralelas e Inspección paralela, y los puntos de interrupción condicionales y de filtro. Al completar este tutorial, te familiarizas con las características de Visual Studio para depurar aplicaciones multiproceso.
Estos dos artículos proporcionan información adicional sobre el uso de otras herramientas de depuración multiproceso:
Para usar la barra de herramientas Ubicación de depuración y la ventana Subprocesos , consulte Tutorial: Depuración de una aplicación multiproceso.
Para ver un ejemplo que usa Task (código administrado) y el entorno de ejecución de simultaneidad (C++), consulte Tutorial: Depuración de una aplicación paralela. Para obtener sugerencias generales de depuración que se aplican a la mayoría de los tipos de aplicaciones multiproceso, lea tanto ese artículo como este.
El primer paso es crear un proyecto de aplicación multiproceso.
Creación de un proyecto de aplicación multiproceso
Abra Visual Studio y cree un proyecto.
Si la ventana de inicio no está abierta, elija Archivo>Iniciar ventana.
En la ventana de inicio, elija Crear un nuevo proyecto.
En la ventana Crear un nuevo proyecto, escriba console en el cuadro de búsqueda. A continuación, elija C#, C++o Visual Basic en la lista Lenguaje y, a continuación, elija Windows en la lista Plataforma.
Después de aplicar los filtros de lenguaje y plataforma, elija la plantilla Aplicación de consola para .NET o C++y, a continuación, elija Siguiente.
Nota:
Si no ve la plantilla correcta, vaya a Herramientas>Obtener herramientas y características..., que abre el Instalador de Visual Studio. Elija la carga de trabajo Desarrollo de escritorio de .NET o Desarrollo de escritorio con C++ y, a continuación, elija Modificar.
En la ventana Configurar el nuevo proyecto, escriba o introduzca MyThreadWalkthroughApp en el cuadro Nombre del proyecto. A continuación, elija Siguiente o Crear, la opción que esté disponible.
Para un proyecto de .NET Core o .NET 5+, elija la plataforma de destino recomendada o .NET 8 y, a continuación, elija Crear.
Aparece un nuevo proyecto de consola. Una vez creado el proyecto, aparece un archivo de origen. Según el idioma que haya elegido, es posible que se llame al archivo de origen Program.cs, MyThreadWalkthroughApp.cpp o Module1.vb.
Elimine el código que aparece en el archivo de origen y reemplácelo por el código actualizado siguiente. Elija el fragmento de código adecuado para la configuración del código.
using System; using System.Threading; public class ServerClass { static int count = 0; // The method that will be called when the thread is started. public void InstanceMethod() { Console.WriteLine( "ServerClass.InstanceMethod is running on another thread."); int data = count++; // Pause for a moment to provide a delay to make // threads more apparent. Thread.Sleep(3000); Console.WriteLine( "The instance method called by the worker thread has ended. " + data); } } public class Simple { public static void Main() { for (int i = 0; i < 10; i++) { CreateThreads(); } } public static void CreateThreads() { ServerClass serverObject = new ServerClass(); Thread InstanceCaller = new Thread(new ThreadStart(serverObject.InstanceMethod)); // Start the thread. InstanceCaller.Start(); Console.WriteLine("The Main() thread calls this after " + "starting the new InstanceCaller thread."); } }
En el menú Archivo, seleccione Guardar todo.
(Solo Visual Basic) En el Explorador de soluciones (panel derecho), haga clic con el botón derecho en el nodo del proyecto y elija Propiedades. En la pestaña Aplicación , cambie el objeto Startup a Simple.
Depuración de la aplicación multiproceso
En el editor de código fuente, busque el siguiente fragmento de código:
Haga clic con el botón izquierdo en el margen izquierdo de la
Thread.Sleep
instrucción o, para C++,std::this_thread::sleep_for
para insertar un nuevo punto de interrupción.En el margen, un círculo rojo indica que se ha establecido un punto de interrupción en esta ubicación.
En el menú Depurar , seleccione Iniciar depuración (F5).
Visual Studio compila la solución, la aplicación comienza a ejecutarse con el depurador asociado y, a continuación, la aplicación se detiene en el punto de interrupción.
En el editor de código fuente, busque la línea que contiene el punto de interrupción.
Detección del marcador de subproceso
En la barra de herramientas de depuración, seleccione el botón Mostrar subprocesos en código fuente
.
Presione F11 dos veces para avanzar el depurador.
Mire el canalón en el lado izquierdo de la ventana. En esta línea verá un icono de marcador de subproceso
que se parece a dos hilos entrelazados. El marcador de subproceso indica que un subproceso se detiene en esta ubicación.
Un punto de interrupción puede ocultar parcialmente un marcador de subproceso.
Pase el puntero sobre el marcador de hilo. Aparece un DataTip que indica el nombre y el ID del hilo para cada hilo detenido. En este caso, el nombre es probablemente
<noname>
.Seleccione el marcador de subproceso para ver las opciones disponibles en el menú contextual.
Visualización de ubicaciones de subprocesos
En la ventana Pilas paralelas , puede cambiar entre una vista Subprocesos y la vista Tareas (para la programación basada en tareas) y puede ver la información de pila de llamadas para cada subproceso. En esta aplicación, podemos usar la vista de hilos.
Abra la ventana Pilas paralelas seleccionando Depurar>pilas paralelas de>. Debería ver algo parecido a lo siguiente. La información exacta puede diferir en función de la ubicación actual de cada subproceso, el hardware y el lenguaje de programación.
En este ejemplo, de izquierda a derecha vemos esta información para el código administrado:
- El subproceso actual (flecha amarilla) ha entrado en
ServerClass.InstanceMethod
. Para ver el identificador de subproceso y el marco de pila de un subproceso, mantenga el puntero sobreServerClass.InstanceMethod
. - El subproceso 31724 está esperando un bloqueo propiedad del subproceso 20272.
- El subproceso principal (lado izquierdo) se ha detenido en [Código externo], que puede ver con detalle si elige Mostrar código externo.
En este ejemplo, de izquierda a derecha vemos esta información para el código administrado:
- El subproceso principal (lado izquierdo) se ha detenido en
Thread.Start
, donde el punto de detención se identifica mediante el icono de marcador de subproceso.
- Dos subprocesos han entrado en
ServerClass.InstanceMethod
, uno de los cuales es el subproceso actual (flecha amarilla), mientras que el otro subproceso se ha detenido enThread.Sleep
. - También se inicia un nuevo subproceso (a la derecha), pero se detiene en
ThreadHelper.ThreadStart
.
- El subproceso actual (flecha amarilla) ha entrado en
Para ver los subprocesos en una vista de lista, seleccione Depurar>Windows>Subprocesos.
En esta vista, puede ver fácilmente que el subproceso 20272 es el subproceso principal y actualmente se encuentra en código externo, específicamente System.Console.dll.
Nota:
Para obtener más información sobre el uso de la ventana Subprocesos , vea Tutorial: Depuración de una aplicación multiproceso.
Haga clic con el botón derecho en las entradas de la ventana Pilas paralelas o Subprocesos para ver las opciones disponibles en el menú contextual.
Puede realizar varias acciones en estos menús con el botón derecho. En este tutorial, explorará con más profundidad los detalles de la ventana Inspección paralela en las siguientes secciones.
Establecimiento de una inspección en una variable
Abra la ventana Inspección Paralela seleccionando Depurar>Windows>Inspección Paralela>Inspección Paralela 1.
Seleccione la celda donde verá el
<Add Watch>
texto (o la celda de encabezado vacía en la cuarta columna) y escribadata
.Los valores de la variable de datos para cada subproceso aparecen en la ventana.
Seleccione la celda donde verá el
<Add Watch>
texto (o la celda de encabezado vacía en la quinta columna) y escribacount
.Los valores de la
count
variable para cada subproceso aparecen en la ventana. Si todavía no ve mucha información, intente presionar F11 varias veces para avanzar la ejecución de los subprocesos en el depurador.Haga clic con el botón derecho en una de las filas de la ventana para ver las opciones disponibles.
Marcar y desmarcar subprocesos
Puede marcar subprocesos para realizar un seguimiento de los subprocesos importantes e ignorar los demás subprocesos.
En la ventana Inspección paralela , mantenga presionada la tecla Mayús y seleccione varias filas.
Haga clic con el botón derecho y seleccione Marca.
Se marcarán todos los subprocesos seleccionados. Ahora, puedes filtrar para mostrar solo los hilos marcados.
En la ventana Inspección Paralela, seleccione el botón Mostrar solo subprocesos marcados
.
Solo los hilos marcados aparecen en la lista.
Sugerencia
Después de marcar algunos subprocesos, puede hacer clic con el botón derecho en una línea de código en el editor de código y elegir Ejecutar subprocesos marcados en cursor. Asegúrese de elegir código al que accedan todos los subprocesos marcados. Visual Studio pausará los subprocesos en la línea de código seleccionada, lo que facilita el control del orden de ejecución mediante la congelación y el descongelamiento de subprocesos.
Seleccione el botón Mostrar solo subprocesos marcados de nuevo para volver a activar el modo Mostrar todos los subprocesos .
Para quitar los marcadores de subprocesos, haga clic con el botón derecho en uno o más subprocesos marcados en la ventana Inspección paralela y seleccione Quitar marca.
Inmovilización y reanudación de la ejecución de subprocesos
Sugerencia
Puede congelar y descongelar (suspender y reanudar) subprocesos para controlar el orden en el que los subprocesos realizan su trabajo. Esto puede ayudarle a resolver incidencias de simultaneidad como interbloqueos y condiciones de carrera.
En la ventana Inspección paralela, con todas las filas seleccionadas, haga clic con el botón derecho y seleccione Inmovilizar.
En la segunda columna, aparece un icono de pausa para cada fila. El icono de pausa indica que el subproceso está inmovilizado.
Anule la selección de todas las demás filas seleccionando solo una fila.
Haga clic con el botón derecho en una fila y seleccione Reanudar.
El icono de pausa desaparece de esta fila, lo que indica que el subproceso ya no está inmovilizado.
Cambie al editor de código y presione F11. Solo se ejecuta el subproceso inmovilizado.
La aplicación también puede crear instancias de algunos subprocesos nuevos. Los subprocesos nuevos no están marcados ni se inmovilizan.
Seguimiento de un solo subproceso con puntos de interrupción condicionales
Puede ser útil seguir la ejecución de un único subproceso en el depurador. Una forma de hacerlo consiste en inmovilizar los subprocesos que no le interesan. En algunos escenarios, es posible que tenga que seguir un único subproceso sin inmovilizar otros subprocesos, por ejemplo, para reproducir un error determinado. Para seguir un subproceso sin inmovilizar los demás, debe evitar interrumpir el código, excepto en el subproceso que le interese. Puede realizar esta tarea estableciendo un punto de interrupción condicional.
Puede establecer puntos de interrupción en condiciones diferentes, como el nombre del subproceso o el identificador de subproceso. Puede resultar útil establecer la condición en los datos que sabe que son únicos para cada subproceso. Este enfoque es común durante la depuración si le interesa más algún valor de datos concreto que cualquier subproceso concreto.
Haga clic con el botón derecho en el punto de interrupción que creó anteriormente y seleccione Condiciones.
En la ventana Configuración del punto de interrupción , escriba
data == 5
para la expresión condicional.Sugerencia
Si estás más interesado en un subproceso específico, usa un nombre de subproceso o un identificador de subproceso como condición. Para ello, en la ventana Configuración del punto de interrupción , seleccione Filtrar en lugar de Expresión condicional y siga las sugerencias de filtro. Es posible que quiera asignar un nombre a los subprocesos en el código de la aplicación, ya que los identificadores de subprocesos cambian al reiniciar el depurador.
Cierre la ventana Configuración del punto de interrupción .
Seleccione el botón de Reiniciar
para volver a iniciar la sesión de depuración.
Se interrumpe el código en el subproceso en el que el valor de la variable de datos es 5. En la ventana Inspección paralela, busque la flecha de color amarillo que indica el contexto del depurador actual.
Ahora, puede depurar el código paso a paso por procedimientos (F10) y paso a paso por instrucciones (F11), y seguir la ejecución del subproceso único.
Siempre y cuando la condición de punto de interrupción sea única para el subproceso, y el depurador no alcance ningún otro punto de interrupción en otros subprocesos (es posible que tenga que deshabilitarlos), puede depurar el código paso a paso por procedimientos y por instrucciones sin cambiar a otros subprocesos.
Nota:
Al avanzar el depurador, se ejecutarán todos los subprocesos. Pero el depurador no interrumpirá el código en otros subprocesos a menos que uno llegue a un punto de interrupción.