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.
En este tutorial se muestra cómo usar las ventanas Tareas paralelas y Pilas paralelas para depurar una aplicación paralela. Estas ventanas le ayudan a comprender y comprobar el comportamiento en tiempo de ejecución del código que usa la biblioteca paralela de tareas (TPL) o el runtime de simultaneidad. En este tutorial se proporciona código de ejemplo que tiene puntos de interrupción integrados. Una vez que se interrumpe el código, el tutorial muestra cómo usar las ventanas Tareas paralelas y Pilas paralelas para examinarlo.
En este tutorial se enseñan estas tareas:
Cómo ver las pilas de llamadas de todos los subprocesos en una sola vista.
Cómo ver la lista de
System.Threading.Tasks.Task
instancias que se crean en la aplicación.Cómo ver las pilas de invocación reales de tareas en vez de subprocesos.
Cómo navegar hacia el código desde las ventanas de Tareas paralelas y Pilas paralelas.
Cómo las ventanas se enfrentan a la escala mediante la agrupación, el zoom y otras características relacionadas.
Prerrequisitos
En este tutorial se supone que Solo mi código está habilitado (está habilitado de forma predeterminada en versiones más recientes de Visual Studio). En el menú Herramientas, seleccione Opciones, expanda el nodo Depuración, seleccione General y, a continuación, seleccione Habilitar solo mi código (solo administrado). Si no establece esta característica, puede seguir usando este tutorial, pero los resultados pueden diferir de las ilustraciones.
Ejemplo de C#
Si usa el ejemplo de C#, en este tutorial también se supone que el código externo está oculto. Para alternar si se muestra código externo, haga clic con el botón derecho en el encabezado de la tabla Nombre de la ventana Pila de llamadas y, a continuación, seleccione o desactive Mostrar código externo. Si no establece esta característica, puede seguir usando este tutorial, pero los resultados pueden diferir de las ilustraciones.
Ejemplo de C++
Si usa el ejemplo de C++, puede omitir las referencias al código externo de este artículo. El código externo solo se aplica al ejemplo de C#.
Ilustraciones
Las ilustraciones de este artículo se registran en un equipo de cuatro núcleos que ejecuta el ejemplo de C#. Aunque puede usar otras configuraciones para completar esta guía, las ilustraciones pueden diferir de lo que se muestra en su ordenador.
Creación del proyecto de ejemplo
El código de ejemplo de este tutorial es para una aplicación que no hace nada. El propósito del ejercicio es comprender cómo usar las ventanas de herramientas para depurar una aplicación paralela.
Abra Visual Studio y cree un proyecto.
Si la ventana de inicio no está abierta, elija Archivo>Ventana de inicio.
En la ventana de inicio, elija Nuevo proyecto.
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 aplicación de consola para .NET Core 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 un nombre o use el nombre predeterminado en el cuadro Nombre del proyecto. A continuación, elija Siguiente o Crear, la opción que esté disponible.
En .NET Core, elija la plataforma de destino recomendada o .NET 8 y, después, elija Crear.
Aparece un nuevo proyecto de consola. Una vez creado el proyecto, aparece un archivo de origen.
Abra el archivo de código .cpp, .cs o .vb en el proyecto. Elimine su contenido para crear un archivo de código vacío.
Pegue el código siguiente para el idioma elegido en el archivo de código vacío.
using System; using System.Threading; using System.Threading.Tasks; using System.Diagnostics; class S { static void Main() { pcount = Environment.ProcessorCount; Console.WriteLine("Proc count = " + pcount); ThreadPool.SetMinThreads(4, -1); ThreadPool.SetMaxThreads(4, -1); t1 = new Task(A, 1); t2 = new Task(A, 2); t3 = new Task(A, 3); t4 = new Task(A, 4); Console.WriteLine("Starting t1 " + t1.Id.ToString()); t1.Start(); Console.WriteLine("Starting t2 " + t2.Id.ToString()); t2.Start(); Console.WriteLine("Starting t3 " + t3.Id.ToString()); t3.Start(); Console.WriteLine("Starting t4 " + t4.Id.ToString()); t4.Start(); Console.ReadLine(); } static void A(object o) { B(o); } static void B(object o) { C(o); } static void C(object o) { int temp = (int)o; Interlocked.Increment(ref aa); while (aa < 4) { ; } if (temp == 1) { // BP1 - all tasks in C Debugger.Break(); waitFor1 = false; } else { while (waitFor1) { ; } } switch (temp) { case 1: D(o); break; case 2: F(o); break; case 3: case 4: I(o); break; default: Debug.Assert(false, "fool"); break; } } static void D(object o) { E(o); } static void E(object o) { // break here at the same time as H and K while (bb < 2) { ; } //BP2 - 1 in E, 2 in H, 3 in J, 4 in K Debugger.Break(); Interlocked.Increment(ref bb); //after L(o); } static void F(object o) { G(o); } static void G(object o) { H(o); } static void H(object o) { // break here at the same time as E and K Interlocked.Increment(ref bb); Monitor.Enter(mylock); while (bb < 3) { ; } Monitor.Exit(mylock); //after L(o); } static void I(object o) { J(o); } static void J(object o) { int temp2 = (int)o; switch (temp2) { case 3: t4.Wait(); break; case 4: K(o); break; default: Debug.Assert(false, "fool2"); break; } } static void K(object o) { // break here at the same time as E and H Interlocked.Increment(ref bb); Monitor.Enter(mylock); while (bb < 3) { ; } Monitor.Exit(mylock); //after L(o); } static void L(object oo) { int temp3 = (int)oo; switch (temp3) { case 1: M(oo); break; case 2: N(oo); break; case 4: O(oo); break; default: Debug.Assert(false, "fool3"); break; } } static void M(object o) { // breaks here at the same time as N and Q Interlocked.Increment(ref cc); while (cc < 3) { ; } //BP3 - 1 in M, 2 in N, 3 still in J, 4 in O, 5 in Q Debugger.Break(); Interlocked.Increment(ref cc); while (true) Thread.Sleep(500); // for ever } static void N(object o) { // breaks here at the same time as M and Q Interlocked.Increment(ref cc); while (cc < 4) { ; } R(o); } static void O(object o) { Task t5 = Task.Factory.StartNew(P, TaskCreationOptions.AttachedToParent); t5.Wait(); R(o); } static void P() { Console.WriteLine("t5 runs " + Task.CurrentId.ToString()); Q(); } static void Q() { // breaks here at the same time as N and M Interlocked.Increment(ref cc); while (cc < 4) { ; } // task 5 dies here freeing task 4 (its parent) Console.WriteLine("t5 dies " + Task.CurrentId.ToString()); waitFor5 = false; } static void R(object o) { if ((int)o == 2) { //wait for task5 to die while (waitFor5) { ;} int i; //spin up all procs for (i = 0; i < pcount - 4; i++) { Task t = Task.Factory.StartNew(() => { while (true);}); Console.WriteLine("Started task " + t.Id.ToString()); } Task.Factory.StartNew(T, i + 1 + 5, TaskCreationOptions.AttachedToParent); //scheduled Task.Factory.StartNew(T, i + 2 + 5, TaskCreationOptions.AttachedToParent); //scheduled Task.Factory.StartNew(T, i + 3 + 5, TaskCreationOptions.AttachedToParent); //scheduled Task.Factory.StartNew(T, i + 4 + 5, TaskCreationOptions.AttachedToParent); //scheduled Task.Factory.StartNew(T, (i + 5 + 5).ToString(), TaskCreationOptions.AttachedToParent); //scheduled //BP4 - 1 in M, 2 in R, 3 in J, 4 in R, 5 died Debugger.Break(); } else { Debug.Assert((int)o == 4); t3.Wait(); } } static void T(object o) { Console.WriteLine("Scheduled run " + Task.CurrentId.ToString()); } static Task t1, t2, t3, t4; static int aa = 0; static int bb = 0; static int cc = 0; static bool waitFor1 = true; static bool waitFor5 = true; static int pcount; static S mylock = new S(); }
Después de actualizar el archivo de código, guarde los cambios y compile la solución.
En el menú Archivo, seleccione Guardar todo.
En el menú Compilar , seleccione Recompilar solución.
Observe que hay cuatro llamadas a Debugger.Break
(DebugBreak
en el ejemplo de C++). Por lo tanto, no es necesario insertar puntos de interrupción. Simplemente al ejecutar la aplicación, genera una interrupción en el depurador hasta cuatro veces.
Usar la ventana Pilas Paralelas: Vista de subprocesos
Para comenzar, en el menú Depurar , seleccione Iniciar depuración. Espere hasta que se alcance el primer punto de interrupción.
Visualización de la pila de llamadas de un único subproceso
En el menú Depurar , seleccione Windows y, a continuación, seleccione Subprocesos. Acoplar la ventana Subprocesos en la parte inferior de Visual Studio.
En el menú Depurar , seleccione Windows y, a continuación, seleccione Pila de llamadas. Acopla la ventana Pila de llamadas en la parte inferior de Visual Studio.
Haga doble clic en un subproceso en la ventana Subprocesos para establecerlo como actual. Los hilos actuales tienen una flecha amarilla. Al cambiar el subproceso actual, su pila de llamadas se muestra en la ventana Pila de llamadas .
Examinar la ventana de pilas paralelas
En el menú Depurar , seleccione Windows y, a continuación, seleccione Pilas paralelas. Asegúrese de que Subprocesos está seleccionado en el cuadro de la esquina superior izquierda.
Mediante la ventana Pilas paralelas , puede ver varias pilas de llamadas al mismo tiempo en una vista. En la ilustración siguiente se muestra la ventana Pilas paralelas encima de la ventana Pila de llamadas .
La pila de llamadas del subproceso Main aparece en un cuadro y las pilas de llamadas de los otros cuatro subprocesos se agrupan en otro cuadro. Se agrupan cuatro subprocesos porque sus marcos de pila comparten los mismos contextos de método; es decir, están en los mismos métodos: A
, B
y C
. Para ver los identificadores de subproceso y los nombres de los subprocesos que comparten el mismo cuadro, mantenga el puntero sobre el cuadro con el encabezado ([#] Subprocesos). El hilo actual se muestra en negrita.
La flecha amarilla indica el marco de pila activo del hilo actual.
Puede establecer la cantidad de detalles que se van a mostrar para los marcos de pila (nombres de módulo, tipos de parámetros, nombres de parámetros, valores de parámetro, números de línea y desplazamientos de bytes) haciendo clic con el botón derecho en la ventana Pila de llamadas.
Un resaltado azul alrededor de un cuadro indica que el hilo actual forma parte de ese cuadro. El subproceso actual también se indica mediante el marco de pila en negrita de la información sobre herramientas. Si hace doble clic en el subproceso principal de la ventana Subprocesos, puede observar que la flecha de resaltado de la ventana Pilas paralelas se mueve en consecuencia.
Reanudación de la ejecución hasta el segundo punto de interrupción
Para reanudar la ejecución hasta que se alcance el segundo punto de interrupción, en el menú Depurar , seleccione Continuar. En la ilustración siguiente se muestra el árbol de subprocesos en el segundo punto de interrupción.
En el primer punto de interrupción, cuatro subprocesos pasaron de métodos S.A a S.B a S.C. Esa información sigue siendo visible en la ventana Pilas paralelas, pero los cuatro subprocesos han avanzado aún más. Uno de ellos continuó hacia S.D y luego S.E. Otro continuó hacia S.F, S.G y S.H. Otros dos continuaron hacia S.I y S.J, y desde allí uno de ellos fue a S.K y el otro continuó hasta Nonuser External Code.
Puede pasar el ratón sobre marcos de pila para ver los identificadores de subprocesos y otros detalles del marco. El resaltado azul indica el subproceso actual y la flecha amarilla indica el cuadro de pila activo del subproceso actual.
Puede mantener el puntero sobre el encabezado de cuadro, por ejemplo, 1 subproceso o 2 subprocesos, para ver los identificadores de los subprocesos. Puede pasar el ratón sobre marcos de pila para ver los identificadores de subprocesos y otros detalles del marco. El resaltado azul indica el subproceso actual y la flecha amarilla indica el cuadro de pila activo del subproceso actual.
El icono de hilos de tela (líneas intercaladas) indica los marcos de pila activos de los subprocesos nocurrentes. En la ventana Pila de llamadas, haga doble clic en S.B para cambiar de contexto. La ventana Pilas paralelas indica el marco de pila actual del subproceso actual mediante un icono de flecha curvada.
Nota:
Para obtener una descripción de todos los iconos de la ventana Pilas paralelas, consulte Uso de la ventana Pilas paralelas.
En la ventana Subprocesos , cambie entre subprocesos y observe que la vista de la ventana Pilas paralelas se actualiza.
Puede cambiar a otro subproceso o a otro marco de otro subproceso mediante el menú contextual de la ventana Pilas paralelas . Por ejemplo, haga clic con el botón derecho en S.J, seleccione Cambiar a marco y, a continuación, seleccione un comando.
Haga clic con el botón derecho en S.C y seleccione Cambiar a marco. Uno de los comandos tiene una marca de verificación que indica el marco de pila del hilo actual. Puede cambiar a ese marco del mismo subproceso (solo se mueve la flecha curvada) o puede cambiar al otro subproceso (el resaltado azul también se mueve). En la ilustración siguiente se muestra el submenú.
Cuando un contexto de método está asociado a solo un marco de pila, el encabezado de cuadro muestra 1 subproceso y puede cambiar a él haciendo doble clic. Si hace doble clic en un contexto de método que tiene más de 1 marco asociado, el menú aparece automáticamente. Al mantener el puntero sobre los contextos del método, observe el triángulo negro a la derecha. Al hacer clic en ese triángulo también se muestra el menú contextual.
Para aplicaciones de gran tamaño que tienen muchos subprocesos, es posible que quiera centrarse en solo un subconjunto de subprocesos. La ventana Pilas paralelas solo puede mostrar pilas de llamadas para subprocesos marcados. Para marcar subprocesos, use el menú contextual o la primera celda de un subproceso.
En la barra de herramientas, seleccione el botón Mostrar solo marcado junto al cuadro de lista.
Ahora, solo se muestran los hilos marcados en la ventana Pilas paralelas.
Reanudación de la ejecución hasta el tercer punto de interrupción
Para reanudar la ejecución hasta que se alcance el tercer punto de interrupción, en el menú Depurar , seleccione Continuar.
Cuando varios subprocesos están en el mismo método, pero el método no estaba al principio de la pila de llamadas, el método aparece en cuadros diferentes. Un ejemplo en el punto de inflexión actual es S.L, que tiene tres subprocesos y aparece en tres cajas. Haga doble clic en S.L.
Observe que S.L está en negrita en los otros dos cuadros para que pueda ver dónde más aparece. Si desea ver qué fotogramas llaman a S.L y a cuáles llama S.L, seleccione el botón Cambiar a vista de método en la barra de herramientas. En la ilustración siguiente se muestra la vista de método de la ventana Pilas paralelas .
Observe cómo el diagrama se centra pivotando en el método seleccionado y lo ubica en su caja propia en el centro de la vista. Las llamadas y autores de llamadas aparecen en la parte superior e inferior, respectivamente. Seleccione nuevamente el botón Alternar vista de método para salir de este modo.
El menú contextual de la ventana Pilas paralelas también tiene los siguientes elementos.
Visualización hexadecimal alterna los números en los tooltips entre decimal y hexadecimal.
Configuración de símbolos abre los cuadros de diálogo respectivos.
Mostrar hilos en el código alterna la visualización de marcadores de hilos, indicando su ubicación en el código fuente.
Mostrar código externo muestra todos los fotogramas aunque no estén en el código de usuario. Inténtalo para ver cómo se expande el diagrama para acomodar los otros marcos (que podrían atenuarse porque no tienes símbolos para ellos).
En la ventana Pilas paralelas , asegúrese de que el botón Desplazarse automáticamente al marco de pila actual de la barra de herramientas está activado.
Cuando tiene diagramas grandes y pasa al siguiente punto de interrupción, quizás desee que la vista se desplace automáticamente hasta el marco de pila activo del subproceso actual; es decir, el del subproceso que alcanzó primero el punto de interrupción.
Antes de continuar, en la ventana Pilas paralelas , desplácese hasta la izquierda y hacia abajo.
Reanudación de la ejecución hasta el cuarto punto de interrupción
Para reanudar la ejecución hasta que se alcance el cuarto punto de interrupción, en el menú Depurar , seleccione Continuar.
Observe cómo la vista se desplazó automáticamente a su lugar. Cambie los subprocesos de la ventana Subprocesos o cambie los marcos de pila en la ventana Pila de llamadas y observe cómo la vista siempre se desplaza automáticamente al marco correcto. Desactive la opción Desplazamiento Automático al Marco de Herramienta Actual y vea la diferencia.
La Vista de Pájaro también ayuda con diagramas grandes en la ventana Pilas Paralelas. De forma predeterminada, la vista de pájaro está activada. Puede activarlo o desactivarlo haciendo clic en el botón entre las barras de desplazamiento en la esquina inferior derecha de la ventana, como se muestra en la ilustración siguiente.
En la vista del pájaro, puede mover el rectángulo para desplazarse rápidamente alrededor del diagrama.
Otra manera de mover el diagrama en cualquier dirección es seleccionar un área en blanco del diagrama y arrastrarlo donde quiera.
Para acercar y alejar el diagrama, mantenga presionada la tecla CTRL mientras mueve la rueda del mouse. Como alternativa, seleccione el botón Zoom de la barra de herramientas y, a continuación, use la herramienta Zoom.
También puede ver las pilas de arriba hacia abajo en lugar de abajo hacia arriba, haciendo clic en el menú Herramientas, en Opciones y, a continuación, seleccione o desactive la opción en el nodo Depuración.
Antes de continuar, en el menú Depurar , seleccione Detener depuración para finalizar la ejecución.
Usar la ventana de Tareas Paralelas y la vista de Tareas de la Ventana de Pilas Paralelas
Se recomienda completar los procedimientos anteriores antes de continuar.
Reinicie la aplicación hasta que se alcance el primer punto de interrupción:
En el menú Depurar , seleccione Iniciar depuración y espere a que se alcance el primer punto de interrupción.
En el menú Depurar , seleccione Windows y, a continuación, seleccione Subprocesos. Acoplar la ventana Subprocesos en la parte inferior de Visual Studio.
En el menú Depurar, apunte a Windows y seleccione Pila de llamadas. Acoplar la ventana Pila de llamadas en la parte inferior de Visual Studio.
Haga doble clic en un subproceso en la ventana Subprocesos para establecerlo como actual. Los hilos actuales tienen la flecha amarilla. Al cambiar el hilo actual, se actualizan las demás ventanas. A continuación, examinamos las tareas.
En el menú Depurar , seleccione Windows y, a continuación, seleccione Tareas. En la ilustración siguiente se muestra la ventana Tareas .
Para cada tarea en ejecución, puede leer su identificador, que devuelve la propiedad del mismo nombre, el identificador y el nombre del subproceso que la ejecuta, así como su ubicación (al mantener el puntero sobre ella, se muestra una información sobre herramientas con toda la pila de llamadas). Además, en la columna Tarea , puede ver el método que se pasó a la tarea; es decir, el punto de partida.
Puede ordenar cualquier columna. Observe el glifo de ordenación que indica la columna de ordenación y la dirección. También puede reordenar las columnas arrastrándolas de izquierda o derecha.
La flecha amarilla indica la tarea actual. Puede cambiar las tareas haciendo doble clic en una tarea o mediante el menú contextual. Al cambiar las tareas, el subproceso subyacente se vuelve actual y se actualizan las demás ventanas.
Cuando cambia manualmente de una tarea a otra, el contorno de flecha indica el contexto actual del depurador para una tarea no actual.
Cuando cambia manualmente de una tarea a otra, la flecha amarilla se mueve, pero una flecha blanca todavía muestra la tarea que provocó que el depurador se interrumpa.
Reanudación de la ejecución hasta el segundo punto de interrupción
Para reanudar la ejecución hasta que se alcance el segundo punto de interrupción, en el menú Depurar , seleccione Continuar.
Anteriormente, la columna Estado mostraba todas las tareas como Activas, pero ahora dos de las tareas están bloqueadas. Las tareas se pueden bloquear por muchas razones diferentes. En la columna Estado , mantenga el puntero sobre una tarea en espera para saber por qué está bloqueado. Por ejemplo, en la ilustración siguiente, la tarea 11 está esperando la tarea 12.
Anteriormente, la columna Estado mostraba todas las tareas como Activas, pero ahora dos de las tareas están bloqueadas. Las tareas se pueden bloquear por muchas razones diferentes. En la columna Estado , mantenga el puntero sobre una tarea en espera para saber por qué está bloqueado. Por ejemplo, en la siguiente ilustración, la tarea 4 está esperando a la tarea 5.
La tarea 4, a su vez, está esperando en el monitor del hilo asignado a la tarea 2. (Haga clic con el botón derecho en la fila de encabezado y elija Columnas.>Asignación de subprocesos para ver el valor de asignación de subprocesos de la tarea 2).
Puede marcar una tarea haciendo clic en la marca de la primera columna de la ventana Tareas .
Puede usar la marcación para realizar un seguimiento de las tareas entre distintos puntos de interrupción en la misma sesión de depuración o para filtrar las tareas cuyas pilas de llamadas se muestran en la ventana Pilas paralelas .
Cuando usó la ventana Pilas paralelas anteriormente, ha visto los subprocesos de la aplicación. Vuelva a ver la ventana Pilas paralelas , pero esta vez vea las tareas de la aplicación. Para ello, seleccione Tareas en el cuadro de la esquina superior izquierda. En la ilustración siguiente se muestra la vista Tareas.
Los subprocesos que actualmente no ejecutan tareas no se muestran en la vista Tareas de la ventana Pilas paralelas . Además, para los subprocesos que ejecutan tareas, algunos de los marcos de pila que no son relevantes para las tareas se filtran desde la parte superior e inferior de la pila.
Vuelva a ver la ventana Tareas . Haga clic con el botón derecho en cualquier encabezado de columna para ver un menú contextual para la columna.
Puede usar el menú contextual para agregar o quitar columnas. Por ejemplo, la columna AppDomain no está seleccionada; por lo tanto, no se muestra en la lista. Seleccione Padre. La columna Padre aparece sin valores en cualquiera de las cuatro tareas.
Reanudación de la ejecución hasta el tercer punto de interrupción
Para reanudar la ejecución hasta que se alcance el tercer punto de interrupción, en el menú Depurar , seleccione Continuar.
En este ejemplo, observe que la tarea 11 y la tarea 12 se ejecutan en el mismo subproceso (muestre la columna Asignación de subprocesos si está oculta). Esta información no se muestra en la ventana Subprocesos ; verlo aquí es otra ventaja de la ventana Tareas . Para confirmarlo, vea la ventana Pilas paralelas . Asegúrese de que está viendo Tareas. Puede localizar las tareas 11 y 12 examinando la información sobre herramientas en la ventana Pilas paralelas .
Ahora se está ejecutando una nueva tarea, tarea 5, y la tarea 4 está esperando. Para ver por qué, mantenga el puntero sobre la tarea en espera en la ventana Estado . En la columna Padre, observe que la tarea 4 es el padre de la tarea 5.
Para visualizar mejor la relación padre-hijo, haga clic con el botón derecho en la fila del encabezado de columna y luego seleccione Vista de Padre e Hijo. Debería ver la siguiente ilustración.
Observe que la tarea 4 y la tarea 5 se ejecutan en el mismo subproceso (muestre la columna Asignación de subprocesos si está oculta). Esta información no se muestra en la ventana Subprocesos ; verlo aquí es otra ventaja de la ventana Tareas . Para confirmarlo, vea la ventana Pilas paralelas . Asegúrese de que está viendo Tareas. Busque las tareas 4 y 5 haciendo doble clic en ellas en la ventana Tareas . Cuando lo hace, se actualiza el resaltado azul en la ventana Pilas paralelas . También puede localizar las tareas 4 y 5 explorando la información sobre herramientas en la ventana Pilas paralelas.
En la ventana Pilas paralelas, haga clic con el botón derecho en S.P y luego seleccione Ir al hilo. La ventana cambia a la vista de subprocesos y el marco correspondiente se muestra. Puedes ver ambas tareas en el mismo hilo.
Esta es otra ventaja de la vista Tareas en la ventana Pilas paralelas, en comparación con la ventana Subprocesos.
Reanudación de la ejecución hasta el cuarto punto de interrupción
Para reanudar la ejecución hasta que se alcance el tercer punto de interrupción, en el menú Depurar , seleccione Continuar. Seleccione el encabezado de columna id . para ordenar por identificador. Debería ver la siguiente ilustración.
La tarea 10 y la tarea 11 ahora están esperando entre sí y están bloqueadas. También hay varias tareas nuevas que ahora están programadas. Las tareas programadas son tareas que se han iniciado en el código, pero que aún no se han ejecutado. Por lo tanto, sus columnas Ubicación y asignación de subprocesos muestran mensajes predeterminados o están vacíos.
Dado que la tarea 5 se ha completado, ya no se muestra. Si no es así en tu ordenador y el bloqueo no se muestra, avanza una vez paso a paso presionando F11.
La tarea 3 y la tarea 4 ahora están esperando entre sí y están bloqueadas. También hay 5 nuevas tareas que son elementos secundarios de la tarea 2 y ahora están programadas. Las tareas programadas son tareas que se han iniciado en el código, pero que aún no se han ejecutado. Por lo tanto, sus columnas Ubicación y asignación de subprocesos están vacías.
Vuelva a ver la ventana Pilas paralelas . El encabezado de cada cuadro tiene una información sobre herramientas que muestra los identificadores y nombres del subproceso. Cambie a la Vista de Tareas en la ventana Pilas paralelas. Mantenga el puntero sobre un encabezado para ver el identificador y el nombre de la tarea y el estado de la tarea, como se muestra en la ilustración siguiente.
Puede agrupar las tareas por columna. En la ventana Tareas , haga clic con el botón derecho en el encabezado de columna Estado y seleccione Agrupar por estado. En la ilustración siguiente se muestra la ventana Tareas agrupada por estado.
Puede agrupar también por cualquier otra columna. Al agrupar tareas, puede centrarse en un subconjunto de tareas. Cada grupo contraíble tiene un recuento de los elementos agrupados.
La última característica de la ventana Tareas que se va a examinar es el menú contextual que se muestra al hacer clic con el botón derecho en una tarea.
El menú contextual muestra distintos comandos, en función del estado de la tarea. Los comandos pueden incluir Copiar, Seleccionar todo, Mostrar hexadecimal, Cambiar a tarea, Inmovilizar subproceso asignado, Inmovilizar todos los subprocesos excepto este y Descongelar subproceso asignado y Marca.
Puede congelar el subproceso subyacente de una tarea o tareas, o bien puede congelar todos los subprocesos excepto el asignado. Un subproceso inmovilizado se representa en la ventana Tareas tal y como en la ventana Subprocesos, mediante un icono de pausa azul.
Resumen
En este tutorial se muestran las ventanas del depurador Tareas paralelas y Pilas paralelas . Use estas ventanas en proyectos reales que usan código multiproceso. Puede examinar el código paralelo escrito en C++, C#o Visual Basic.