Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
O Visual Studio fornece várias ferramentas e elementos de interface do usuário para ajudar você a depurar aplicativos multithreaded. Este tutorial mostra como usar marcadores de thread, a janela Pilhas Paralelas, a janela Inspeção Paralela, pontos de interrupção condicionais e pontos de interrupção de filtro. A conclusão deste tutorial familiariza você com os recursos do Visual Studio para depuração de aplicativos multithread.
Para ver tutoriais mais focados em cenários, consulte os artigos a seguir.
A primeira etapa é criar um projeto de aplicativo multithreaded.
Criar um projeto de aplicativo multithreaded
Abra o Visual Studio e crie um novo projeto.
Se a janela inicial não estiver aberta, escolha Arquivo>Janela de Início.
Na janela inicial, escolha Criar um novo projeto.
Na janela Criar um novo projeto , insira ou digite o console na caixa de pesquisa. Em seguida, escolha C#, C++ou Visual Basic na lista de idiomas e escolha o Windows na lista plataforma.
Depois de aplicar os filtros de linguagem e plataforma, escolha o modelo de Aplicativo de Console para .NET ou C++e escolha Avançar.
Observação
Se você não vir o modelo correto, vá para Ferramentas>Obter Ferramentas e Recursos..., o que abre o Instalador do Visual Studio. Escolha a carga de trabalho Desenvolvimento para desktop com .NET ou Desenvolvimento para desktop com C++ e, em seguida, selecione Modificar.
Na janela Configurar seu novo projeto, digite ou insira MyThreadWalkthroughApp na caixa de nome do Projeto . Em seguida, escolha Avançar ou Criar, qualquer opção disponível.
Para um projeto .NET Core ou .NET 5+, escolha a estrutura de destino recomendada ou o .NET 8 e, em seguida, escolha Criar.
Um novo projeto de console aparece. Depois que o projeto for criado, um arquivo de origem será exibido. Dependendo do idioma escolhido, o arquivo de origem pode ser chamado Program.cs, MyThreadWalkthroughApp.cpp ou Module1.vb.
Exclua o código que aparece no arquivo de origem e substitua-o pelo código atualizado a seguir. Escolha o snippet apropriado para sua configuração de código.
using System; using System.Threading; public class ServerClass { static int count = 0; // The method that will be called when the thread is started. public void InstanceMethod() { Console.WriteLine( "ServerClass.InstanceMethod is running on another thread."); int data = count++; // Pause for a moment to provide a delay to make // threads more apparent. Thread.Sleep(3000); Console.WriteLine( "The instance method called by the worker thread has ended. " + data); } } public class Simple { public static void Main() { for (int i = 0; i < 10; i++) { CreateThreads(); } } public static void CreateThreads() { ServerClass serverObject = new ServerClass(); Thread InstanceCaller = new Thread(new ThreadStart(serverObject.InstanceMethod)); // Start the thread. InstanceCaller.Start(); Console.WriteLine("The Main() thread calls this after " + "starting the new InstanceCaller thread."); } }No menu Arquivo, selecione Salvar Tudo.
(Somente Visual Basic) No Gerenciador de Soluções (painel direito), clique com o botão direito do mouse no nó do projeto, escolha Propriedades. Na guia Aplicativo , altere o objeto Inicialização para Simples.
Depurar o aplicativo multithreaded
No editor de código-fonte, procure o seguinte snippet de código:
Clique com o botão esquerdo na medianiz esquerda da instrução
Thread.Sleepou, para C++,std::this_thread::sleep_for, para inserir um novo ponto de interrupção.Na sarjeta, um círculo vermelho indica que um ponto de interrupção está definido neste local.
No menu Depurar , selecione Iniciar Depuração (F5).
O Visual Studio cria a solução, o aplicativo começa a ser executado com o depurador anexado e, em seguida, o aplicativo para no ponto de interrupção.
No editor de código-fonte, localize a linha que contém o ponto de interrupção.
Descubra o marcador de tópicos
Na barra de ferramentas de depuração, selecione o botão Mostrar threads na origem
.Pressione F11 duas vezes para avançar o depurador.
Examine a medianiz no lado esquerdo da janela. Nessa linha, observe um ícone marcador de thread
que se assemelha a dois threads retorcidos. O marcador de thread indica que um thread é interrompido neste local.Um marcador de threads pode ser parcialmente ocultado por um ponto de interrupção.
Passe o ponteiro sobre o marcador de thread. O DataTip aparece, mostrando o nome e o número de ID do thread para cada thread interrompido. Nesse caso, o nome provavelmente é
<noname>.
Selecione o marcador de tópico para ver as opções disponíveis no menu de atalho.
Exibir as localizações do tópico
Na janela Pilhas Paralelas, você pode alternar entre o modo de exibição Threads e o modo de exibição Tarefas (para programação baseada em tarefas) e visualizar as informações de pilha de chamadas para cada thread. Neste aplicativo, podemos usar o modo de exibição Threads.
Abra a janela Pilhas Paralelas escolhendo Depurar>Windows>Pilhas Paralelas. Você deverá ver algo semelhante ao mostrado a seguir. As informações exatas podem ser diferentes dependendo da localização atual de cada thread, do hardware e da linguagem de programação.
Neste exemplo, da esquerda para a direita, vemos essas informações para o código gerenciado:
- O thread atual (seta amarela) inseriu
ServerClass.InstanceMethod. Você pode exibir a ID do thread e o quadro de pilha de um thread passando o mouse sobreServerClass.InstanceMethod. - O thread 31724 está aguardando um bloqueio pertencente ao thread 20272.
- O thread principal (lado esquerdo) parou em [código externo], que você pode exibir em detalhes se escolher Mostrar código externo.
Neste exemplo, da esquerda para a direita, vemos essas informações para o código gerenciado:
- O fio Principal no lado esquerdo foi interrompido em
Thread.Start, onde o ponto de parada é identificado pelo ícone marcador de fio
. - Dois threads entraram em
ServerClass.InstanceMethod, sendo que um deles é o thread atual (seta amarela), enquanto o outro thread parou emThread.Sleep. - Um novo thread (à direita) também está sendo iniciado, mas é interrompido em
ThreadHelper.ThreadStart.
Observação
Para obter mais informações sobre como usar a exibição Threads , consulte Depurar um deadlock usando a exibição Threads.
- O thread atual (seta amarela) inseriu
Para exibir os threads em vista de lista, selecione Depurar>Windows>Threads.
Nesse modo de exibição, você pode ver facilmente que o thread 20272 é o thread Principal e atualmente está localizado em código externo, especificamente System.Console.dll.
Clique com o botão direito do mouse em entradas na janela Pilhas Paralelas ou Threads para ver as opções disponíveis no menu de atalho.
Você pode executar várias ações nesses menus com o botão direito do mouse. Para este tutorial, você explorará mais desses detalhes na janela Inspeção Paralela (próximas seções).
Monitorar uma variável
Abra a janela Inspeção Paralela selecionando Depurar>Windows>Inspeção Paralela>Inspeção Paralela 1.
Selecione a célula em que você vê o
<Add Watch>texto (ou a célula de cabeçalho vazia na quarta coluna) e insiradata.Os valores da variável de dados para cada thread aparecem na janela.
Selecione a célula em que você vê o
<Add Watch>texto (ou a célula de cabeçalho vazia na quinta coluna) e insiracount.Os valores da
countvariável para cada thread aparecem na janela. Se você ainda não vir essas informações, tente pressionar F11 algumas vezes para avançar a execução dos threads no depurador.
Clique com o botão direito do mouse em uma das linhas na janela para ver as opções disponíveis.
Sinalizar e remover sinalizador de threads
Você pode marcar tópicos para acompanhar os tópicos importantes e ignorar os outros.
Na janela Inspeção Paralela , mantenha pressionada a tecla Shift e selecione várias linhas.
Clique com o botão direito do mouse e selecione Sinalizador.
Todos os threads selecionados são sinalizados. Agora, você pode filtrar para mostrar apenas threads sinalizados.
Na janela Inspeção Paralela , selecione o botão Mostrar Somente Threads Sinalizados
.Somente os threads sinalizados aparecem na lista.
Dica
Depois de sinalizar alguns threads, você pode clicar com o botão direito do mouse em uma linha de código no editor de código e escolher Executar Threads Sinalizados no Cursor. Certifique-se de escolher os códigos que será atingidos por todos os threads sinalizados. O Visual Studio pausará threads na linha de código selecionada, facilitando o controle da ordem de execução congelando e descongelando threads.
Selecione o botão Mostrar Somente Threads Sinalizados novamente para alternar novamente para o modo Mostrar Todos os Threads .
Para descomplagar threads, clique com o botão direito do mouse em um ou mais threads sinalizados na janela Inspeção Paralela e selecione Descomplagar.
Congelar e descongelar a execução do thread
Dica
Você pode congelar e descongelar (suspender e retomar) threads para controlar a ordem na qual os threads executam o trabalho. Isso pode ajudar você a resolver problemas de simultaneidade, como deadlocks e condições de corrida.
Na janela Inspeção Paralela, com todas as linhas selecionadas, clique com o botão direito do mouse e selecione Congelar.
Na segunda coluna, um ícone de pausa é exibido para cada linha. O ícone de pausa indica que o thread está congelado.
Desmarque todas as outras linhas selecionando apenas uma linha.
Clique com o botão direito do mouse em uma linha e selecione Descongelar.
O ícone de pausa desaparece nessa linha, o que indica que o thread não está mais congelado.
Alterne para o editor de código e pressione F11. Somente o thread não descongelado é executado.
O aplicativo também pode criar alguns novos threads. Os novos threads não são marcados e não são congelados.
Seguir um thread com pontos de interrupção condicionais
Pode ser útil seguir a execução de apenas um thread no depurador. Uma maneira de fazer isso é congelando threads nos quais você não está interessado. Em alguns cenários, talvez seja necessário seguir um único thread sem congelar outros threads, por exemplo, para reproduzir um bug específico. Para seguir um thread sem congelar outros threads, você deve evitar invadir o código, exceto no thread no qual você está interessado. Você pode fazer essa tarefa definindo um ponto de interrupção condicional.
Você pode definir pontos de interrupção em condições diferentes, como o nome do thread ou a ID do thread. Pode ser útil definir a condição em dados que você sabe que são exclusivos para cada thread. Essa abordagem é comum durante a depuração, quando você está mais interessado em algum valor de dados específico do que em um thread específico.
Clique com o botão direito do mouse no ponto de interrupção criado anteriormente e selecione Condições.
Na janela Configurações do Ponto de Interrupção, insira
data == 5para a expressão condicional.
Ponto Dica
Se você estiver mais interessado em um thread específico, use um nome de thread ou ID de thread para a condição. Para fazer isso na janela Configurações do Ponto de Interrupção , selecione Filtrar em vez de expressão condicional e siga as dicas de filtro. Talvez você queira nomear seus threads no código do aplicativo, pois as IDs de threads mudam quando você reinicia o depurador.
Feche a janela Configurações do Ponto de Interrupção .
Selecione o botão
para reiniciar a sessão de depuração.Você divide o código no thread em que o valor da variável de dados é 5. Na janela Inspeção Paralela, procure a seta amarela que indica o contexto atual do depurador.
Agora, você pode fazer step-over do código (F10) e step-in do código (F11) e seguir a execução do thread único.
Desde que a condição do ponto de interrupção seja exclusiva da thread e o depurador não atinja nenhum outro ponto de interrupção em outras threads (talvez seja necessário desabilitá-los), você pode passar por cima do código e entrar no código sem alternar para outras threads.
Observação
Quando você avança o depurador, todos os threads são executados. No entanto, o depurador não será interrompido em código em outros threads, a menos que um dos outros threads atinja um ponto de interrupção.