Compartilhar via


Demonstra 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 aplicativo em 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 ou Runtime de simultaneidade. 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 no 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

Você deve ter Visual Studio 2010 instalado no computador.

Esta explicação passo a passo presume que Just My Code está habilitado. No Ferramentas menu, clique em Opções, expanda o depuração nó, selecione Gerale selecione Habilitar Just My Code (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 está oculta. Para alternar se código externo é exibido, clique com o botão direito do nome cabeçalho da tabela 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 se aplica somente 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 o 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 objetivo é apenas entender como usar a ferramenta windows para depurar um aplicativo em paralelo.

Para criar o projeto de amostra

  1. In Visual Studio, on the File menu, point to New and then click Project.

  2. No Modelos instalados painel, selecione Visual C#, Visual Basic ou Visual C++. Para os idiomas gerenciados, certifique-se de que .NET Framework 4 é exibido na caixa ' Estrutura '.

  3. Selecione Aplicativo de Console e, em seguida, clique em OK. Permanecerão na configuração de depuração, 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. On the File menu, click Save All.

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

    Observe que há quatro chamadas para Debugger.Break (DebugBreak na amostra de C++), portanto, não é necessário inserir pontos de interrupção; Basta executar o aplicativo fará com que ele quebrar no depurador até quatro vezes.

Usando a janela de pilhas paralela: Visualização de threads

On the Debug menu, click Start Debugging. Aguarde até que o primeiro ponto de interrupção sejam atingidos.

Para exibir a pilha de chamadas de um único segmento.

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

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

  3. Clique duas vezes em um thread na segmentos janela para torná-lo atual. Segmentos atuais têm uma seta amarela. Quando você altera o segmento atual, sua pilha de chamada é exibida no Call Stack janela.

Examine a janela de pilhas paralela

  • No Debug , aponte para Windows e, em seguida, clique em Paralela pilhas. Certifique-se de que segmentos está selecionado 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 a Call Stack janela.

    Janela Pilhas Paralelas na exibição Threads

    A 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 porque seus quadros de pilha compartilham a mesma contextos de método. ou seja, eles são os mesmos métodos: A, B, and C. Para exibir os IDs de segmento 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 IDs e nomes de threads

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

    Dica de ferramenta em quadro de pilha ativa

    Você pode definir quantos detalhes para mostrar os quadros de pilha (Nomes do módulo, Tipos de parâmetro, Nomes de parâmetro, Os valores de parâmetro, Números de linha e Deslocamentos de bytes) clicando no Call Stack janela.

    Um realce azul ao redor de uma caixa indica que o thread atual é parte da caixa. O thread atual também é indicado pelo quadro de pilha em negrito na dica de ferramenta. Se você clicar duas vezes o thread principal na janela Threads, você pode observar que o realce azul na Paralela pilhas janela move de acordo.

    Pilhas com o 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 é atingido, diante a Debug menu, clique em continuar. A ilustração a seguir mostra a árvore de thread no segundo ponto de interrupção.

    Janela Pilhas Paralelas com muitas ramificações

    No primeiro ponto de interrupção, quatro segmentos de todos os passaram de s. para S.B para métodos S.C. Que informações ainda estão visíveis no Paralela pilhas janela, mas com quatro segmentos têm progrediu ainda mais. Um deles continuou a S.D e, em seguida, Sudeste Outro 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 não-usuário de código externo.

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

    O ícone de threads de tecido (azuis e vermelhos ondulado, linhas sobrepostas) indicam que os quadros de pilha active segmentos não-circulantes. No Call Stack janela, clique duas vezes em S.B para comutar estruturas. O Paralela pilhas janela indica o quadro de pilha atual do segmento atual usando o ícone de seta curva verde.

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

    Você pode alternar para outro thread ou para outro quadro de outro segmento, usando o menu de atalho do Paralela pilhas janela. Por exemplo, S.J com o botão direito, aponte para Switch para o quadroe clique em um comando.

    Caminho de execução de pilhas paralelas

    S.C com o botão direito e aponte para Switch para o quadro. Um dos comandos tem uma marca de seleção indica o quadro de pilha do thread atual. Você pode alternar para o quadro do mesmo segmento (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 contexto de método está associado ao quadro de apenas uma pilha, o cabeçalho de caixa exibe do Thread 1 e você pode alternar para ele clicando duas vezes. Se clicar duas vezes em um contexto de método 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 o menu de atalho.

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

    Janela Pilhas Vazias e dica de ferramenta

    Em seguida, na segmentos janela, um por um, para ver como suas pilhas de chamada aparecem em threads do sinalizador a Paralela pilhas janela. Para sinalizar threads, use o menu de atalho ou a primeira célula de um thread. Clique o Mostrar sinalizado somente botão da 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 é atingido, diante a Debug 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 chamada, 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 outras duas caixas para que você possa ver o lugar onde ela aparece. Se você quiser ver quais quadros chamada S.L e quais quadros chamadas, clique o 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 em sua própria caixa no meio do modo de exibição. Os chamados e chamadores aparecem na parte superior e inferior. Clique o Alternar modo de exibição do método botão novamente para deixar esse modo.

    O menu de atalho da Paralela pilhas janela 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 abre as caixas de diálogo correspondente.

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

    • 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 a 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, convém o modo de exibição para a rolagem automática para o quadro ativo de pilha do thread atual; ou seja, o segmento atingiu 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 na barra de ferramentas está no.

    Autorrolagem na janela Pilhas Paralelas

  2. Antes de continuar, na Paralela pilhas janela, todo o caminho para a esquerda e até o final de rolagem.

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

  1. Para continuar a execução até que o quarto ponto de interrupção é atingido, diante a Debug menu, clique em continuar.

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

    O Vista panorâmica também ajuda com grandes diagramas no Paralela pilhas janela. Você pode ver o Vista panorâmica , clicando no botão entre as barras de rolagem para o 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 de rapidamente se enquadrar em torno do diagrama.

    Outra maneira de mover o diagrama em qualquer direção é uma área vazia do diagrama de clique e arraste-a onde você deseja.

    Para aplicar mais zoom dentro e fora do diagrama, pressione e mantenha 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 com exibição ampliada e reduzida

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

  2. Antes de continuar, na Debug menu, clique em Stop Debugging a fim de execução.

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. No Debug menu, clique em Start Debugging e aguarde o primeiro ponto de interrupção sejam atingidos.

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

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

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

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

    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 propriedade de mesmo nome, o ID e o nome do segmento que é executado, sua localização (focalizando que exibe uma dica de ferramenta que possui a pilha de chamadas inteira). 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 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 tarefa atual. Você pode alternar tarefas clicando duas vezes em uma tarefa ou usando o menu de atalho. Quando você alternar tarefas, o thread subjacente se torna atual e outras janelas são atualizadas.

    Quando você alterna manualmente de uma tarefa para outro, a move a seta amarela, 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 é atingido, diante a Debug 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 sinalizador na primeira coluna da Tarefas paralelas janela.

    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 pilhas janela.

    Quando usado o Paralela pilhas janela anterior, você exibiu os threads do aplicativo. Modo de exibição de Pilhas paralela janela 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 Pilhas paralela janela. Além disso, para os threads que executam tarefas, alguns dos quadros de pilha que não são relevantes para as tarefas são filtradas superior e inferior da pilha.

    Modo de exibição de Tarefas paralelas janela novamente. Clique com o botão direito qualquer cabeçalho de coluna para ver um menu de atalho para a coluna.

    Menu de cabeçalho de colunas Tarefas Paralelas

    Você pode usar o menu de atalho para adicionar ou remover colunas. Por exemplo, a coluna de AppDomain não é selecionada; Portanto, não é exibido na lista. Clique em pai. O pai coluna aparece sem valores para qualquer um dos 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 é atingido, diante a Debug menu, clique em continuar.

    Uma nova tarefa, a tarefa 5, agora está em execução e agora está aguardando a tarefa 4. Você pode ver o motivo pelo qual focalizando a tarefa de espera na Status janela. No pai coluna, observe que a tarefa 4 é o pai da tarefa 5.

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

    Exibição de tarefas paralelas na exibição pai-filho

    Observe que a tarefa 4 e 5 de tarefa em execução no mesmo thread. Essas informações não são exibidas no segmentos janela; vê-lo aqui é outro benefício do Tarefas paralelas janela. Para confirmar isso, exiba o Paralela pilhas janela. Certifique-se de que você está exibindo tarefas. Localize as tarefas, 4 e 5 clicando duas vezes na Tarefas paralelas janela. Quando você faz, o realce azul no Paralela pilhas janela é atualizada. Você também pode localizar tarefas 4 e 5, examinando as dicas de ferramentas na Paralela pilhas janela.

    Janela Pilhas Paralelas na exibição de tarefas

    No Paralela pilhas janela, clique com o botão direito p e clique em Ir Thread. A janela alterna para o modo de exibição de Threads e o quadro correspondente está em 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 segmentos janela.

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

  • Para continuar a execução até que o terceiro ponto de interrupção é atingido, diante a Debug menu, clique em continuar. Clique o ID cabeçalho de coluna para classificar por ID. Você deve 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 caso em seu computador e o bloqueio não for mostrado, etapa uma vez pressionando F11.

    Tarefas 3 e 4 agora estão aguardando em si 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 pilhas janela novamente. O cabeçalho de cada caixa tem uma dica de ferramenta mostra os nomes e identificações de segmento. Alterne para modo de exibição de tarefas no Paralela pilhas janela. Focalize um cabeçalho para ver a identificação da tarefa e o nome e o status da tarefa, conforme mostrado na ilustração a seguir.

    Janela Pilhas Paralelas com dica de ferramenta de cabeçalho

    Você pode agrupar 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 paralelas janela agrupados por status.

    Janela Tarefas Paralelas com tarefas agrupadas

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

    Janela Tarefas Paralelas agrupada

    O último recurso da Tarefas paralelas é de janela para examinar o menu de atalho é exibido quando o botão direito do mouse uma tarefa.

    Menu de contexto expandido da janela Tarefas Paralelas

    O menu de atalho exibe 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 tarefa ou tarefas, ou você pode congelar todos os threads, exceto aquele atribuído. Um thread congelado é representado no Tarefas paralelas janela como ela está na segmentos janela, por um azul Pausar ícone.

Summary

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 código multithread. Você pode examinar o código paralelo escrito em C++, C# ou Visual Basic.

Consulte também

Tarefas

Demonstra Passo a passo: Depurando um aplicativo paralelo

Usando a janela de pilhas paralela

Usando a janela de tarefas paralelas

Conceitos

Programação em paralela a.NET Framework

Runtime de simultaneidade

Outros recursos

Guia para o depurador

Depurando código gerenciado