Compartilhar via


Passo a passo: Depurando um aplicativo paralelo

Esta explicação passo a passo mostra como usar o Tarefas paralelas e Paralela pilhas windows para depurar um aplicativoem paralelo.Essas janelas ajudam a compreender e verificar o comportamento de tempo de execução de código que usa o Biblioteca paralela de tarefas (TPL) ou o Tempo de execução de concorrência.Esta explicação passo a passo fornece código de exemplo que tem pontos de interrupção internos.Depois que o código é interrompida, a explicação passo a passo mostra como usar o Tarefas paralelas e Paralela pilhas windows examiná-lo.

Esta explicação passo a passo ensina essas tarefas:

  • Como exibir as pilhas de chamadas de todos os threads em um modo de exibição.

  • Como exibir a lista de System.Threading.Tasks.Task instâncias que são criadas em seu aplicativo.

  • Como exibir as pilhas de chamadas real das tarefas em vez de threads.

  • Como navegar até o código da Tarefas paralelas e Paralela pilhas windows.

  • Como os windows lidar com escala por meio do agrupamento, zoom e outros recursos relacionados.

Pré-requisitos

Esta explicação passo a passo presume que Apenas Meu Código está habilitado.No Ferramentas menu, clique em Opções, expandir o Debugging nó, selecione Gerale selecione Permitir que o Apenas Meu Código (somente gerenciado). Se você não definir esse recurso, você ainda pode usar este passo a passo, mas os resultados podem ser diferentes das ilustrações.

Exemplo C#

Se você usar a amostra de C#, este passo a passo também pressupõe que o código externo é oculto.Para indicar se o código externo é exibido, clique com o botão direito do nome tabela de cabeçalho da Call Stack janela, em seguida, marque ou desmarque Show External Code. Se você não definir esse recurso, você ainda pode usar este passo a passo, mas os resultados podem ser diferentes das ilustrações.

Exemplo de C++

Se você usar a amostra de C++, você pode ignorar as referências ao código externo neste tópico.Código externo só se aplica a amostra de C#.

Ilustrações

As ilustrações deste tópico é gravado em um computador quad-core, executando o exemplo C#.Embora você possa usar outras configurações para concluir este passo a passo, as ilustrações podem diferir do que é exibido em seu computador.

Criando o projeto de amostra

Esta explicação passo a passo o código de exemplo é para um aplicativo que não faz nada.O meta é apenas entender como usar a ferramenta windows para depurar um aplicativoem paralelo.

Para criar o projeto de exemplo

  1. No Visual Studio, no menu Arquivo, aponte para Novo e, em seguida, clique em Projeto.

  2. No Modelos instaladosopainel, selecione Visual C#, Visual Basicou Visual C++. Para os idiomas gerenciado , certifique-se que .NET Framework 4 é exibido na caixa de framework.

  3. Selecione Aplicativo de Console e, em seguida, clique em OK.Permanecem na configuraçãode depuração, que é o padrão.

  4. Abra o arquivo de código. vb,. cs ou. cpp no projeto.Exclua seu conteúdo para criar um arquivo de código vazio.

  5. Cole o seguinte código para sua linguagem escolhida para o arquivo de código vazio.

Imports System
Imports System.Threading
Imports System.Threading.Tasks
Imports System.Diagnostics

Module S

  Sub Main()

    pcount = Environment.ProcessorCount
    Console.WriteLine("Proc count = " + pcount.ToString())
    ThreadPool.SetMinThreads(4, -1)
    ThreadPool.SetMaxThreads(4, -1)

    t1 = New Task(AddressOf A, 1)
    t2 = New Task(AddressOf A, 2)
    t3 = New Task(AddressOf A, 3)
    t4 = New Task(AddressOf 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()
  End Sub
  Sub A(ByVal o As Object)
    B(o)
  End Sub
  Sub B(ByVal o As Object)
    C(o)
  End Sub
  Sub C(ByVal o As Object)

    Dim temp As Integer = o

    Interlocked.Increment(aa)
    While (aa < 4)
    End While

    If (temp = 1) Then
      ' BP1 - all tasks in C
      Debugger.Break()
      waitFor1 = False
    Else
      While (waitFor1)
      End While
    End If
    Select Case temp
      Case 1
        D(o)
      Case 2
        F(o)
      Case 3, 4
        I(o)
      Case Else
        Debug.Assert(False, "fool")
    End Select
  End Sub
  Sub D(ByVal o As Object)
    E(o)
  End Sub
  Sub E(ByVal o As Object)
    ' break here at the same time as H and K
    While (bb < 2)
    End While
    'BP2 - 1 in E, 2 in H, 3 in J, 4 in K
    Debugger.Break()
    Interlocked.Increment(bb)

    'after
    L(o)
  End Sub
  Sub F(ByVal o As Object)
    G(o)
  End Sub
  Sub G(ByVal o As Object)
    H(o)
  End Sub
  Sub H(ByVal o As Object)
    ' break here at the same time as E and K
    Interlocked.Increment(bb)
    Monitor.Enter(mylock)
    While (bb < 3)
    End While
    Monitor.Exit(mylock)

    'after
    L(o)
  End Sub
  Sub I(ByVal o As Object)
    J(o)
  End Sub
  Sub J(ByVal o As Object)

    Dim temp2 As Integer = o

    Select Case temp2
      Case 3
        t4.Wait()
      Case 4
        K(o)
      Case Else
        Debug.Assert(False, "fool2")
    End Select
  End Sub
  Sub K(ByVal o As Object)
    ' break here at the same time as E and H
    Interlocked.Increment(bb)
    Monitor.Enter(mylock)
    While (bb < 3)
    End While
    Monitor.Exit(mylock)

    'after
    L(o)
  End Sub
  Sub L(ByVal oo As Object)
    Dim temp3 As Integer = oo

    Select Case temp3
      Case 1
        M(oo)
      Case 2
        N(oo)
      Case 4
        O(oo)
      Case Else
        Debug.Assert(False, "fool3")
    End Select
  End Sub
  Sub M(ByVal o As Object)
    ' breaks here at the same time as N and Q
    Interlocked.Increment(cc)
    While (cc < 3)
    End While

    'BP3 - 1 in M, 2 in N, 3 still in J, 4 in O, 5 in Q
    Debugger.Break()
    Interlocked.Increment(cc)
    While (True)
      Thread.Sleep(500) '  for ever
    End While
  End Sub
  Sub N(ByVal o As Object)
    ' breaks here at the same time as M and Q
    Interlocked.Increment(cc)
    While (cc < 4)
    End While
    R(o)
  End Sub
  Sub O(ByVal o As Object)
    Dim t5 As Task = Task.Factory.StartNew(AddressOf P, TaskCreationOptions.AttachedToParent)
    t5.Wait()
    R(o)
  End Sub
  Sub P()
    Console.WriteLine("t5 runs " + Task.CurrentId.ToString())
    Q()
  End Sub
  Sub Q()
    ' breaks here at the same time as N and M
    Interlocked.Increment(cc)
    While (cc < 4)
    End While
    ' task 5 dies here freeing task 4 (its parent)
    Console.WriteLine("t5 dies " + Task.CurrentId.ToString())
    waitFor5 = False
  End Sub
  Sub R(ByVal o As Object)
    If (o = 2) Then
      ' wait for task5 to die
      While waitFor5
      End While

      '//spin up all procs
      Dim i As Integer
      For i = 0 To pcount - 4 - 1

        Dim t As Task = Task.Factory.StartNew(Sub()
                                                While True

                                                End While
                                              End Sub)
        Console.WriteLine("Started task " + t.Id.ToString())
      Next

      Task.Factory.StartNew(AddressOf T, i + 1 + 5, TaskCreationOptions.AttachedToParent) ' //scheduled
      Task.Factory.StartNew(AddressOf T, i + 2 + 5, TaskCreationOptions.AttachedToParent) ' //scheduled
      Task.Factory.StartNew(AddressOf T, i + 3 + 5, TaskCreationOptions.AttachedToParent) ' //scheduled
      Task.Factory.StartNew(AddressOf T, i + 4 + 5, TaskCreationOptions.AttachedToParent) ' //scheduled
      Task.Factory.StartNew(AddressOf 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(o = 4)
      t3.Wait()
    End If
  End Sub
  Sub T(ByVal o As Object)
    Console.WriteLine("Scheduled run " + Task.CurrentId.ToString())
  End Sub
  Private t1, t2, t3, t4 As Task
  Private aa As Integer = 0
  Private bb As Integer = 0
  Private cc As Integer = 0
  Private waitFor1 As Boolean = True
  Private waitFor5 As Boolean = True
  Private pcount As Integer
  Private mylock As New S2()
End Module

Public Class S2

End Class
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();
}
#include "stdafx.h"
#include <windows.h>
#include <iostream>
#include <ppl.h>
#include <agents.h>
#include <stdio.h>
#include <concrtrm.h>
#include <vector>

CRITICAL_SECTION cs;

using namespace ::std;
using namespace ::std::tr1;
using namespace ::Concurrency;
task_group task4;
task_group task3;
task_group task2;

volatile long aa = 0;
volatile long bb = 0;
volatile long cc = 0;
static bool waitFor1 = true;
static bool waitFor5 = true;

#pragma optimize("", off)
void Spin()
{
   for(int i=0;i<50*50000;++i);
}
#pragma optimize("",on)

template<class Func>
class RunFunc
{
   Func& m_Func;
   int m_o;
public:
   RunFunc(Func func,int o):m_Func(func),m_o(o){

   };
   void operator()()const{
      m_Func(m_o);
   };
};

void T(int o)
{
   cout << "Scheduled run \n";

};

void R(int o)
{
   if (o == 2)
   {
      while (waitFor5) { ;}
      Spin();

      //use up all processors but 4 by scheduling 4 non-terminating tasks.
      int numProcsToBurn = GetProcessorCount() - 4;
      int i;
      vector<call<int>*> tasks;
      for (i = 0; i <  numProcsToBurn; i++)
      {
         tasks.push_back(new call<int>([](int i){while(true)Spin();}));
         asend(tasks[i],1);
         cout << "Started task  \n";
      }

      task_handle<RunFunc<decltype(T)>> t6(RunFunc<decltype(T)>(T,i + 1 + 5));
      task_handle<RunFunc<decltype(T)>> t7(RunFunc<decltype(T)>(T,i + 2 + 5));
      task_handle<RunFunc<decltype(T)>> t8(RunFunc<decltype(T)>(T,i + 3 + 5));
      task_handle<RunFunc<decltype(T)>> t9(RunFunc<decltype(T)>(T,i + 4 + 5));
      task_handle<RunFunc<decltype(T)>> t10(RunFunc<decltype(T)>(T,i + 5 + 5));
      task2.run(t6);
      task2.run(t7);
      task2.run(t8);
      task2.run(t9);
      task2.run(t10);

      //BP4 - 1 in M, 2 in R, 3 in J, 4 in R, 5 died   
      DebugBreak();
   }
   else
   {
      if (o!=4)
         throw;

      task3.wait();      
   }
};

void Q()
{
   // breaks here at the same time as N and M
   InterlockedIncrement(& cc);
   while (cc < 4)
   {
      ;
   }
   // task 5 dies here freeing task 4 (its parent)
   cout << "t5 dies\n";
   waitFor5 = false;
};

void P()
{
   cout << "t5 runs\n";
   Q();
};

void O(int o)
{   
   task_group t5;
   t5.run(&P);
   t5.wait();
   R(o);
};

void N(int o)
{
   // breaks here at the same time as M and Q
   InterlockedIncrement(&cc);
   while (cc < 4)
   {
      ;
   }
   R(o);
};

void M(int o)
{
   // breaks here at the same time as N and Q
   InterlockedIncrement(&cc);
   while (cc < 3)
   {
      ;
   }
   //BP3 - 1 in M, 2 in N, 3 still in J, 4 in O, 5 in Q
   DebugBreak();
   InterlockedIncrement(&cc);
   while (true)
      Sleep(500); // for ever
};

void L(int oo)
{
   int temp3 = oo;

   switch (temp3)
   {
   case 1:
      M(oo);
      break;
   case 2:
      N(oo);
      break;
   case 4:
      O(oo);
      break;
   default:
      throw; //fool3
      break;
   }
}
void K(int o)
{
   // break here at the same time as E and H
   InterlockedIncrement(&bb);
   EnterCriticalSection(&cs);
   while (bb < 3)
   {
      ;
   }
   LeaveCriticalSection(&cs);
   Spin();

   //after
   L(o);
}
void J(int o)
{
   int temp2 = o;

   switch (temp2)
   {
   case 3:
      task4.wait();
      break;
   case 4:
      K(o);
      break;
   default:
      throw; //fool2
      break;
   }
}
static void I(int o)
{
   J(o);
}
static void H(int o)
{
   // break here at the same time as E and K
   InterlockedIncrement(&bb);
   EnterCriticalSection(&cs);
   while (bb < 3)
   {
      ;
   }
   LeaveCriticalSection(&cs);
   Spin();

   //after
   L(o);
}
static void G(int o)
{
   H(o);
}
static void F(int o)
{
   G(o);
}

static void E(int 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   
   Spin(); // for native case only
   DebugBreak();
   InterlockedIncrement(&bb);

   //after
   L(o);

}

static void D(int o)
{
   E(o);
}

static void C(int o)
{
   int temp = o;

   InterlockedIncrement(&aa);
   while (aa < 4)
   {
      ;
   }

   if (temp == 1)
   {
      // BP1 - all tasks in C   
      DebugBreak();
      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:
      throw; //fool
      break;
   }
}
static void B(int o)
{
   C(o);
}

void A(int o)
{
   B(o);
}
int main()
{
   InitializeCriticalSection(&cs);

   task_group tasks;
   task_handle<RunFunc<decltype(A)>> t1(RunFunc<decltype(A)>(A,1));
   tasks.run(t1);
   task_handle<RunFunc<decltype(A)>> t2(RunFunc<decltype(A)>(A,2));
   task2.run(t2);
   task_handle<RunFunc<decltype(A)>> t3(RunFunc<decltype(A)>(A,3));
   task3.run(t3);
   task_handle<RunFunc<decltype(A)>> t4(RunFunc<decltype(A)>(A,4));
   task4.run(t4);

   getchar();
   return 1;
}
  1. No menu File, clique em Save All.

  2. Sobre o Build menu, clique em Rebuild Solution.

    Observe que há quatro chamadas para Debugger.Break (DebugBreak no exemplo de C++), portanto, você não precisará inserir pontos de interrupção; simplesmente executar o aplicativo fará com que ele falhe no depurador até quatro vezes.

Usando a janela de pilhas paralela: visualização de Threads

No menu Depuração, clique em Iniciar Depuração.Aguarde até que o primeiro ponto de interrupção sejam atingidos.

Para exibir a pilha de chamadas de um único thread

  1. Sobre o Debug menu, aponte para Windows e, em seguida, clique em segmentos. Encaixe o segmentosjanela na parte inferior do Visual Studio.

  2. Sobre o Debug menu, aponte para Windows e, em seguida, clique em Call Stack. Encaixe o Call Stackjanela na parte inferior Visual Studio.

  3. Clique duas vezes em um thread a segmentosjanela para torná-lo atual. Segmentos atuais têm uma seta amarela.Quando você altera o threadatual, sua pilha de chamadas é exibido no Call Stackjanela.

Para examinar a pilhas paralela janela

  • Sobre o Debug menu, aponte para Windows e, em seguida, clique em Pilhas paralela. Certifique-se de que segmentos está selecionada na caixa no canto superior esquerdo.

    Usando o Paralela pilhas janela, você pode exibir várias pilhas de chamadas ao mesmo tempo em uma exibição.A ilustração a seguir mostra a Paralela pilhas janela acima do Call Stackjanela.

    Janela pilhas paralelas na exibição de Threads

    pilha de chamadas do thread principal aparece em uma caixa e as pilhas de chamadas para outros quatro segmentos são agrupadas em outra caixa.Quatro segmentos são agrupados juntas, porque seus quadros de pilha compartilham os mesmo método contextos. ou seja, eles são nos mesmos métodos: A, B, e C.Para exibir os IDs de thread e os nomes dos threads que compartilham a mesma caixa, focalize o cabeçalho (4 segmentos).O thread atual é exibido em negrito, como mostrado na ilustração a seguir.

    Dica de ferramenta com nomes e identificações de segmento

    A seta amarela indica o quadro ativo de pilha do threadatual.Para obter mais informações, passe o mouse sobre ele

    Dica de ferramenta no quadro de pilha ativa

    Você pode definir quantos detalhes para mostrar para os quadros de pilha (Nomes do módulo, Tipos de parâmetro, Nomes de parâmetro, Valores de parâmetro, Números de linha e Bytes desloca) clicando no Call Stackjanela.

    Um realce azul ao redor de uma caixa indica que o thread atual faz parte do que a caixa.O thread atual também é indicado pelo quadro de pilha em negrito na dica de ferramenta.Se você clicar duas vezes o principal thread na janelaThreads, você poderá observar que o realce azul na Paralela pilhasjanela se move de acordo.

    Pilhas de thread principal realçado em azul

Para continuar a execução até que o segundo ponto de interrupção

  • Para continuar a execução até que o segundo ponto de interrupção é alcançado, diante do Depurar menu, clique em continuar. A ilustração a seguir mostra aárvore do threadno segundo ponto de interrupção.

    Janela pilhas paralelas com muitas ramificações

    No primeiro ponto de interrupção, todas as quatro segmentos de caiu de s. a para S.B para métodos S.C.Que informações ainda são visíveis no Paralela pilhasjanela, mas os quatro segmentos têm progrediu ainda mais. Um deles continua a S.D e, em seguida, SudesteOutro continuou a S.F, S.G e S.H.Dois outros continuação de S.I e S.J e há uma delas passou para S.K e o outro continua a aplicativos não - código dousuário externo.

    Você pode focalizar caixa cabeçalho, por exemplo, 1 segmento ou 2 segmentos, para ver o thread IDs dos threads.Você pode focalizar os quadros de pilha para ver as identificações de thread além de outros detalhes do quadro .O realce azul indica o thread atual e a seta amarela indica o quadro ativo de pilha do threadatual.

    O ícone de threads de tecido (azuis e vermelhos ondulado, linhas sobrepostas) indicam os quadros de pilha ativo dos threads não-circulantes.No Call Stackjanela, clique duas vezes em S.B para comutar estruturas. O Paralela pilhasjanela indica a pilha quadro atual do thread atual usando um ícone de seta curva verde.

    No segmentos janela, alterna entre segmentos e observe que o modo de exibição a Paralela pilhasjanela é atualizada.

    Você pode alternar para outro threadou para outro quadro de outro thread, usando omenu de atalhona Paralela pilhasjanela. Por exemplo, S.J com o botão direito, aponte para Switch para o quadroe, em seguida, clique em um comando.

    Caminho de pilhas paralelas de execução

    S.C com o botão direito e aponte para Switch para o quadro.Um dos comandos possui uma marca de seleção indica o quadro de pilha do threadatual.Você pode alternar para o quadro do mesmo thread (moverá apenas na seta verde) ou você pode alternar para o outro thread (o realce azul também serão movidos).A ilustração a seguir mostra o submenu.

    Menu pilhas com 2 opções em C, embora J seja o atual

    Quando um métododecontexto está associado a apenas uma pilha de quadro, a caixa cabeçalho exibe do Thread 1 e você pode alternar para ele clicando duas vezes. Se clicar duas vezes em umcontexto de métodoque tem mais de 1 quadro associado a ele, em seguida, no menu automaticamente surgirá. Quando você focaliza os contextos de método , observe o triângulo preto à direita.Clicar nesse triângulo também exibe omenude atalho.

    Para aplicativos grandes que têm muitos segmentos, você poderá se concentrar em apenas um subconjunto de threads.O Paralela pilhasjanela pode exibir pilhas de chamadas somente para threads sinalizados. Na barra de ferramentas, clique no Mostrar sinalizado somente o botão próximo à caixa de listagem.

    Janela pilhas vazias e dica de ferramenta

    Em seguida, no segmentos janela, um por um, para ver a aparecem de suas pilhas de chamadas nos threads do sinalizar de Pilhas paralelajanela. Para segmentos de sinalizar , use omenu de atalhoou a primeira célula de um thread. Clique no Mostrar sinalizado somente botão de barra de ferramentas novamente para mostrar todos os threads.

Para continuar a execução até que o terceiro ponto de interrupção

  1. Para continuar a execução até que o terceiro ponto de interrupção é alcançado, diante do Depurar menu, clique em continuar.

    Quando vários segmentos estão no mesmo método , mas o método não estava no início da pilha de chamadas, o método aparece nas caixas diferentes.Um exemplo no ponto de interrupção atual é S.L, que tem três threads nele e aparece em três caixas.Clique duas vezes em S.L.

    Caminho de execução de pilhas paralelas

    Observe que o S.L está em negrito nas duas caixas para que você possa ver onde mais poderia ser aparece.Se você quiser ver qual a chamada para S.L de quadros e quais quadros chamadas, clique no Alternar modo de exibição do método na barra de ferramentas.A ilustração a seguir mostra o modo de exibição do método a Paralela pilhas janela.

    Janela pilhas na exibição de método

    Observe como o diagrama dinamizado no método selecionado e posicionou na sua própria caixa no meio do modo de exibição.Os chamados e chamadores aparecem na parte superior e inferior.Clique no Alternar modo de exibição do método botão novamente para deixar esse modo.

    Omenu de atalhoda Paralela pilhasjanela também tem os seguintes outros itens.

    • Exibição hexadecimal alterna os números nas dicas de ferramentas entre decimal e hexadecimal.

    • Informações de carga de símbolo e Configurações de símbolo em aberto as caixas de diálogo correspondente.

    • Go To Source Code e Go To Disassembly navegar no editor para o métodoselecionado.

    • Mostrar código externo exibe todos os quadros, mesmo que não estejam no código do usuário .Tente-lo para ver o diagrama expandir para acomodar os quadros adicionais (que podem ser esmaecidos porque você não tem símbolos para eles).

    Quando você tem grandes diagramas e você passar para o próximo ponto de interrupção, é aconselhável o modo de exibição para a rolagem automática ao active pilha quadro do atual thread; ou seja, o thread que alcançou o ponto de interrupção pela primeira vez.No Pilhas paralela janela, certifique-se de que o A rolagem automática para o quadro de pilha atual botão na barra de ferramentas estiver em.

    Autorrolagem na janela pilhas paralelas

  2. Antes de continuar, no Paralela pilhasjanela, todo o caminho para a esquerda e até o final de rolagem.

Para continuar a execução até que o quarto ponto de interrupção

  1. Para continuar a execução até que o quarto ponto de interrupção é alcançado, diante do Depurar menu, clique em continuar.

    Observe como o autoscrolled do modo de exibição no lugar.Alternar os threads na segmentos switch ou ajanela pilha de quadros a Call Stackjanela e observe como o modo de exibição sempre autoscrolls ao quadrocorreto. Desativar A rolagem automática para o quadro atual da ferramenta opção e ver a diferença.

    O Exibição vista panorâmica também ajuda com grandes diagramas no Paralela pilhasjanela. Você pode ver o Exibição vista panorâmica , clicando no botão entre as barras de rolagem no canto inferior direito da janela, conforme mostrado na ilustração a seguir.

    Janela pilhas paralelas com exibição de vista aérea

    Você pode mover o retângulo para se deslocar rapidamente em torno do diagrama.

    Outra maneira de mover o diagrama em qualquer direção é uma área vazia do diagrama de clique e arraste-a no local desejado.

    Para aplicar zoom dentro e fora do diagrama, pressione e segure a tecla CTRL enquanto move a roda do mouse .Como alternativa, clique no botão Zoom na barra de ferramentas e, em seguida, use a ferramenta Zoom.

    Pilhas lado a lado Zoom in e check-out

    Você também pode visualizar as pilhas em uma direção de cima para baixo em vez de baixo para cima, clicando o Ferramentas menu, clique em Opçõese marque ou desmarque a opção sob o depuração nó.

  2. Antes de continuar, diante do Depurar menu, clique em Stop Debugging execução final.

Usando a janela de tarefas paralelas e o modo de exibição de tarefas da janela pilhas paralela

É recomendável que você conclua os procedimentos anteriores antes de continuar.

Para reiniciar o aplicativo até o primeiro ponto de interrupção é atingido

  1. Sobre o Debug menu, clique em Start Debugging e aguarde até que o primeiro ponto de interrupção sejam atingidos.

  2. Sobre o Debug menu, aponte para Windows e, em seguida, clique em segmentos. Encaixe o segmentosjanela na parte inferior do Visual Studio.

  3. Sobre o Debug menu, aponte para Windows e clique em Call Stack. Encaixe o Call Stackjanela na parte inferior Visual Studio.

  4. Clique duas vezes em um thread a segmentosjanela para torna atual. Segmentos atuais têm a seta amarela.Quando você altera o threadatual, as outras janelas são atualizadas.Em seguida, examinaremos as tarefas.

  5. Sobre o Debug menu, aponte para Windows e, em seguida, clique em Tarefas paralelas. A ilustração a seguir mostra a Tarefas paralelasjanela.

    Janela tarefas paralelas com 4 tarefas em execução

    Para cada tarefa em execução, você pode ler a sua identificação, que é retornada pela propriedadede mesmo nome, o ID e o nome do thread que administra, sua localização (focalizando que exibe uma dica de ferramenta que possui a toda pilha de chamadas).Além disso, sob o tarefa coluna, você pode ver o método que foi passado para a tarefa; em outras palavras, o ponto de partida.

    Você pode classificar qualquer coluna.Observe o glifo de classificação que indica a coluna de classificação e a direção.Você também pode reordenar as colunas arrastando-os para esquerda ou direita.

    A seta amarela indica que a tarefaatual.Você pode alternar tarefas clicando duas vezes em uma tarefa ou usando omenude atalho. Quando você alternar tarefas, o thread de subjacente é atualizado e as outras janelas são atualizadas.

    Quando você alterna manualmente de uma tarefa para outro, a seta amarela move, mas uma seta branca ainda mostra a tarefa que causou o depurador para quebrar.

Para continuar a execução até que o segundo ponto de interrupção

  • Para continuar a execução até que o segundo ponto de interrupção é alcançado, diante do Depurar menu, clique em continuar.

    Anteriormente, o Status coluna mostrou todas as tarefas como execução, mas agora duas tarefas estão aguardando.As tarefas podem ser bloqueadas por diversos motivos.No Status coluna, passe o mouse sobre uma tarefa de espera para saber por que ele está bloqueado.Por exemplo, na ilustração a seguir, a tarefa 3 está aguardando a tarefa 4.

    Janela tarefas paralelas com 2 tarefas em espera

    Tarefa 4, por sua vez, está aguardando um monitor do thread atribuído à tarefa 2.

    Janela tarefas com tarefa em espera e dica de ferramenta

    Você pode sinalizar uma tarefa clicando-se o sinalizar na primeira coluna da Tarefas paralelasjanela.

    Você pode usar a sinalização para controlar as tarefas entre diferentes pontos de interrupção na mesma sessão de depuração ou filtrar as tarefas cujas pilhas de chamadas são mostradas na Paralela pilhasjanela.

    Quando foi usado o Pilhas paralelajanela anterior, que foram exibidos os threads do aplicativo . Modo de exibição de Pilhas paralelajanela novamente, mas desta vez exibir as tarefas de aplicativo . Fazer isso selecionando tarefas na caixa no canto superior esquerdo.A ilustração a seguir mostra o modo de exibição de tarefas.

    Janela tarefas paralelas na exibição de tarefas

    Threads que não estão em execução tarefas não são mostrados na exibição de tarefas do Paralela pilhasjanela. Além disso, para os threads que executar tarefas, alguns dos quadros de pilha que não sejam relevantes para as tarefas são filtradas superior e inferior da pilha.

    Modo de exibição de Tarefas paralelasjanela novamente. Clique com o botão direito qualquer cabeçalho de coluna para ver ummenu de atalhopara a coluna.

    Menu de columnheader tarefas paralelas

    Você pode usar omenu de atalhopara adicionar ou remover colunas. Por exemplo, a coluna de AppDomain não está selecionada; Portanto, não é exibido na lista.Clique em pai.O pai coluna aparece sem valores para qualquer uma das quatro tarefas.

Para continuar a execução até que o terceiro ponto de interrupção

  • Para continuar a execução até que o terceiro ponto de interrupção é alcançado, diante do Depurar menu, clique em continuar.

    Uma nova tarefa, tarefa 5, agora está sendo executado e está aguardando a tarefa 4.Você pode ver por que passando sobre a tarefa de espera na Statusjanela. No pai coluna, observe que a tarefa 4 é o pai da tarefa 5.

    Para visualizar melhor a pai -filhorelação, clique com o botão direito do pai cabeçalho da coluna e clique Exibição pai-filho. Você deverá ver a ilustração a seguir.

    Modo de exibição de tarefas paralelo na exibição pai-filho

    Observe que a tarefa 4 e a tarefa 5 estão sendo executados no mesmo thread.Essas informações não são exibidas no segmentosjanela; vê-lo aqui é outro benefício da Tarefas paralelasjanela. Para confirmar isso, exiba o Paralela pilhasjanela. Certifique-se de que você está exibindo tarefas.Localize as tarefas de 4 e 5 clicando duas vezes na Tarefas paralelasjanela. Quando você faz, o realce azul no Paralela pilhasjanela é atualizada. Também é possível localizar tarefas 4 e 5, examinando as dicas de ferramentas na Paralela pilhasjanela.

    Janela pilhas paralelas na exibição de tarefas

    No Paralela pilhas janela, clique com o botão direito p e, em seguida, clique em Ir para Thread. A janela alterna para o modo de Threads e o quadro correspondente está no modo de exibição.Você pode ver ambas as tarefas no mesmo thread.

    Exibição de threads com thread realçado

    Este é outro benefício do modo de exibição de tarefas no Paralela pilhas janela, em comparação comparada o segmentosjanela.

Para continuar a execução até que o quarto ponto de interrupção

  • Para continuar a execução até que o terceiro ponto de interrupção é alcançado, diante do Depurar menu, clique em continuar. Clique no ID cabeçalho da coluna para classificar por ID.Você deverá ver a ilustração a seguir.

    Janela pilhas paralelas com tarefas em 4 Estados

    Porque concluiu a tarefa 5, ele não é mais exibido.Se não for o maiúsculas e minúsculas em seu computador e o deadlock não é mostrada, passo uma vez pressionando F11.

    Tarefa 3 e a tarefa 4 agora estão aguardando uns dos outros e estão bloqueadas.Também existem 5 novas tarefas que são filhos de tarefa 2 e agora estão programadas.Tarefas agendadas são tarefas que foram iniciadas no código, mas ainda não o executaram.Portanto, suas local e A atribuição de segmento colunas estão vazias.

    Exibir o Paralela pilhasjanela novamente. O cabeçalho de cada caixa tem uma dica de ferramenta que mostra os nomes e identificações de thread .Alterne para modo de exibição de tarefas no Paralela pilhasjanela. Passe o mouse sobre um cabeçalho para ver a ID da tarefa e o nome e o status da tarefa, conforme mostrado na ilustração a seguir.

    Janela pilhas paralelas com dica de ferramenta do cabeçalho

    Você pode grupo as tarefas por coluna.No Tarefas paralelas janela, com o botão direito do Status cabeçalho da coluna e clique Agrupar por Status. A ilustração a seguir mostra a Tarefas paralelasjanela agrupados por status.

    Janela tarefas paralelas com tarefas agrupadas

    Você também pode grupo por qualquer outra coluna.Agrupar tarefas, você pode focalizar um subconjunto de tarefas.Cada grupo de recolhível tem uma contagem dos itens que estão agrupadas juntas.Você pode também rapidamente sinalizar todos os itens do grupo clicando o Sinalizador o botão à direita da Recolher botão.

    Janela tarefas paralelas agrupada

    O último recurso da Tarefas paralelasjanela para examinar é omenu de atalhoque é exibido quando o botão direito do mouse uma tarefa.

    Contextmenu de janela tarefas paralela expandido

    Omenu de atalhoexibe comandos diferentes, dependendo do status da tarefa. Os comandos podem incluir Copy, Selecionar tudo, Exibição Hexadecimal, Switch a tarefa, Congelar atribuído Thread, Congelar todos os Threads, mas este, e Descongelar atribuído Thread, e Sinalizador.

    Você pode congelar o thread subjacente de uma tarefaou tarefas, ou poderá congelar todos os threads, exceto aquele atribuído.Um thread de congelados é representado no Tarefas paralelas janela como ela está na segmentos janela, por um azul Pausar ícone.

Resumo

Esta explicação passo a passo demonstrou a Tarefas paralelas e Paralela pilhas o depurador de janelas.Use essas janelas em projetos reais que usam o código multithread.Você pode examinar o código paralelo escrito em C++, C# ou Visual Basic.

Consulte também

Tarefas

Passo a passo: Depurando um aplicativo paralelo

Conceitos

Tempo de execução de concorrência

Usando a janela de pilhas paralela

Usando a janela de tarefas paralelas

Outros recursos

Depurador Roadmap

Depurando código gerenciado

Programação em paralela a.NET Framework