Estamos tendo um aplicativo WPF em que partes dele podem gerar exceções em tempo de execução. Eu gostaria de capturar globalmente qualquer exceção não tratada e registrá-las, mas, caso contrário, continue a execução do programa como se nada tivesse acontecido (como os VBs On Error Resume Next
).
Isso é possível em c #? E se sim, onde exatamente eu precisaria colocar o código de manipulação de exceções?
Atualmente, não consigo ver nenhum ponto em que eu possa quebrar um try
/ catch
ao redor e que capte todas as exceções que possam ocorrer. E mesmo assim eu teria deixado o que foi executado por causa da captura. Ou estou pensando em direções terrivelmente erradas aqui?
ETA: Como muitas pessoas abaixo indicaram: O aplicativo não é para controlar usinas nucleares. Se travar, não é grande coisa, mas as exceções aleatórias relacionadas principalmente à interface do usuário são um incômodo no contexto em que seria usado. Havia (e provavelmente ainda existem) alguns deles, e como ele usa uma arquitetura de plug-in e pode ser estendido por outros (também estudantes nesse caso; portanto, não há desenvolvedores experientes capazes de escrever código completamente livre de erros).
Quanto às exceções detectadas: eu as registro em um arquivo de log, incluindo o rastreamento completo da pilha. Esse era o objetivo desse exercício. Apenas para combater as pessoas que estavam tomando minha analogia com a OERN da VB muito literalmente.
Eu sei que ignorar cegamente certas classes de erros é perigoso e pode corromper minha instância do aplicativo. Como dito anteriormente, este programa não é essencial para ninguém. Ninguém em sã consciência apostaria nela a sobrevivência da civilização humana. É simplesmente uma pequena ferramenta para testar determinadas abordagens de design. Engenharia de software.
Para o uso imediato do aplicativo, não há muitas coisas que podem acontecer em uma exceção:
- Sem tratamento de exceções - diálogo de erro e saída do aplicativo. A experiência deve ser repetida, embora provavelmente com outro assunto. Nenhum erro foi registrado, o que é lamentável.
- Tratamento genérico de exceção - erro benigno interceptado, nenhum dano causado. Este deve ser o caso comum julgado por todos os erros que estávamos vendo durante o desenvolvimento. Ignorar esse tipo de erro não deve ter consequências imediatas; as estruturas de dados principais são testadas o suficiente para sobreviverem facilmente a isso.
- Tratamento de exceção genérico - erro grave interceptado, possivelmente travar em um momento posterior. Isso pode acontecer raramente. Nós nunca vimos isso até agora. O erro é registrado de qualquer maneira e uma falha pode ser inevitável. Portanto, isso é conceitualmente semelhante ao primeiro caso. Exceto que temos um rastreamento de pilha. E na maioria dos casos, o usuário nem percebe.
Quanto aos dados do experimento gerados pelo programa: um erro grave na pior das hipóteses faria com que nenhum dado fosse registrado. Mudanças sutis que alteram um pouco o resultado do experimento são bastante improváveis. E mesmo nesse caso, se os resultados parecerem duvidosos, o erro foi registrado; ainda é possível jogar fora esse ponto de dados, se for um total discrepante.
Para resumir: Sim, eu me considero ainda pelo menos parcialmente sã e não considero uma rotina global de manipulação de exceções que deixa o programa em execução necessariamente necessariamente totalmente mau. Como dito duas vezes antes, essa decisão pode ser válida, dependendo da aplicação. Nesse caso, foi julgada uma decisão válida e não besteira total e absoluta. Para qualquer outro aplicativo, essa decisão pode parecer diferente. Mas, por favor, não me acuse ou a outras pessoas que trabalharam nesse projeto para potencialmente explodir o mundo só porque estamos ignorando erros.
Nota lateral: existe exatamente um usuário para esse aplicativo. Não é algo como o Windows ou o Office que é usado por milhões, onde o custo de ter exceções borbulhar para o usuário já seria muito diferente em primeiro lugar.
On Error Resume Next
não é possível em C #. Depois de umException
(C # não tem "erros"), você não pode simplesmente continuar com a próxima instrução: a execução continuará em umcatch
bloco - ou em um dos manipuladores de eventos descritos nas respostas abaixo.Respostas:
Use o
Application.DispatcherUnhandledException Event
. Veja esta pergunta para um resumo (consulte a resposta de Drew Noakes ).Esteja ciente de que ainda haverá exceções que impedem a retomada bem-sucedida do seu aplicativo, como após um estouro de pilha, memória esgotada ou perda de conectividade de rede enquanto você tenta salvar no banco de dados.
fonte
Código de exemplo usando o NLog que capturará exceções lançadas de todos os threads no AppDomain , do thread do dispatcher interface usuário e das funções assíncronas :
App.xaml.cs:
fonte
UnhandledException
manipulador. Eu tinha de olhar para o Windows Event Log Viewer para encontrar o que estava acontecendo ...e.Handled = true;
noUnhandledException
que a aplicação não irá falhar em Exceções UIEvento AppDomain.UnhandledException
fonte
Além do que outros mencionaram aqui, observe que a combinação de
Application.DispatcherUnhandledException
(e seus similares ) comno
app.config
impedirá que a exceção de encadeamentos secundários encerre o aplicativo.fonte
Aqui está um exemplo completo usando
NLog
fonte
Como "VB's On Error Resume Next?" Isso parece meio assustador. A primeira recomendação é não fazê-lo. A segunda recomendação é não fazê-lo e não pensar nisso. Você precisa isolar melhor suas falhas. Quanto à forma de abordar esse problema, isso depende de como o código está estruturado. Se você estiver usando um padrão como MVC ou similar, isso não deve ser muito difícil e definitivamente não exigiria um engolidor de exceção global. Em segundo lugar, procure uma boa biblioteca de log como log4net ou use rastreamento. Precisamos saber mais detalhes, como quais tipos de exceções você está falando e quais partes do seu aplicativo podem resultar no lançamento de exceções.
fonte