Tive que resolver hoje um bug em uma aplicação que havia construído a tempos. A aplicação faz a importação de um arquivo via web, passa o arquivo para um Serviço NT e retorna. O serviço continua o processamento, em outro processo, em outra thread. A comunicação é via .Net Remoting. Funciona muito bem. Fazer o trabalho na thread do ASP.Net era garantia de bloqueio de recursos e timeout.

Só que a depuração da aplicação integrada dá um pouco de problema. Multi-threaded ainda é mais problema. Serviços NT não são exatamente simples de depurar, você passa por um processo extra. Vou mostrar aqui como se faz isso. Pode parecer óbvio, mas precisa de um pouco de conhecimento sobre o Visual Studio e sobre como threads funcionam.

Estou assumindo que o serviço NT já está instalado na máquina. Selecione a aplicação web como startup da solução, recompile a solution para garantir que o serviço NT vai compilar também. Inicie o debug da aplicação web (nas imagens diminuidas clique para ampliar):

Iniciando a depuração

Assim que a aplicação terminar de compilar:

Compilado

Inicie o serviço:

Iniciando no service.msc

Anexe o processo do Serviço:

Anexando o processo

Janela para anexar o processo

Ele vai aparecer na janela de processes:

Janela de processos com o processo anexado

Como o caso era complicado eu queria saber de qualquer exceção que acontecesse, então no Debug > Exceptions habilitei pegar qualquer exceção que fosse lançada, mesmo que fosse capturada:

Depurando todas as exceções

O serviço roda automaticamente a cada determinado tempo. Um método de verificação de importações com erros foi chamado, e ele tinha um breakpoint pré-configurado:

Breakpoint

Abri a janela:

Janela de threads

E congelei a thread de verificação:

Congelando uma thread

Ficou assim:

Thread congelada

Depois liberei a aplicação. A verificação não ia sair de onde eu queria:

Reiniciando a depuração

Fiz algumas ações na aplicação web que fariam o começo de uma importação, que também iria parar em um breakpoint do serviço. Só que em outra thread. Note a thread congelada, e note também que minhas threads de importação têm nome para facilitar a depuração.

Breakpoint em outra thread

A partir daí eu pude colocar a aplicação no estado que queria para a verificação prosseguir. Congelei então a importação, igualzinho fiz com a thread de verificação, depois soltei a thread de verificação:

Liberando a thread

Dei dois cliques sobre a thread, e o Visual Studio me levou ao código que ela estava executando. A partir daí fui depurar o que precisava. Se precisasse voltar à thread de importação era só congelar uma e começar a outra. Se você não faz isso a cada step no código que você dá ele alterna entre as threads de maneira imprevisível e a depuração fica um inferno.

Quando eu falo que o Visual Studio é a melhor IDE de desenvolvimento do planeta, eu não estou brincando. Isso é poder ou o quê?

Giovanni Bassi

Arquiteto e desenvolvedor, agilista, escalador, provocador. É fundador e CSA da Lambda3. Programa porque gosta. Acredita que pessoas autogerenciadas funcionam melhor e por acreditar que heterarquia é mais eficiente que hierarquia. Foi reconhecido Microsoft MVP há mais de dez anos, dos mais de vinte que atua no mercado. Já palestrou sobre .NET, Rust, microsserviços, JavaScript, TypeScript, Ruby, Node.js, Frontend e Backend, Agile, etc, no Brasil, e no exterior. Liderou grupos de usuários em assuntos como arquitetura de software, Docker, e .NET.