Eu li que devemos capturar apenas exceções que podem ser tratadas, o que torna a captura da classe de exceção base (C # neste caso) uma má idéia (por outras razões). Atualmente, faço parte de um projeto no qual, até agora, ainda não vi nada além da exceção básica sendo capturada. Mencionei que é considerado uma prática ruim fazê-lo, mas a resposta foi "Este serviço precisa ser executado 24 horas por dia, 7 dias por semana, e é assim que é".
Como não tive uma boa resposta sobre como lidar adequadamente com exceções em um programa que precisa ser executado 24/7, agora estou aqui. Não consegui encontrar nenhuma informação / sugestão sobre como lidar com o tratamento de exceções em programas / serviços "críticos" que precisam ser executados o tempo todo (e, neste caso, acredito que pode ser bom se o serviço estiver inativo por um minuto ou dois, portanto, nem mesmo críticos). Eu entendo que depende da natureza exata do programa. Os requisitos para um programa que pode causar problemas com risco de vida são bastante diferentes em comparação com um scanner de registro para um jogo online.
Dois exemplos:
1: Um serviço de digitação antecipada para clientes das ferrovias britânicas, usado quando eles pesquisam on-line estações ferroviárias.
2: Um programa que controla automaticamente os comutadores ferroviários das ferrovias acima, com base em informações em tempo real fornecidas por vários sensores nos trilhos, trens etc.
O primeiro programa provavelmente não causaria um grande problema se fosse interrompido por um minuto ou dois, sendo que o último poderia causar vítimas humanas. Sugestões sobre como lidar com cada um? Ponteiro para onde posso encontrar mais informações e pensamentos sobre esse assunto?
fonte
catch Exception
. Isso não significa que o seu programa funcione , significa que as falhas permitem que o estado do aplicativo seja corrompido enquanto continua sendo executado, um lugar muito mais perigoso para se estar. Um caiu programa pode ser desastroso, mas um programa que está em um estado inválido, mas ainda realizar ações pode ser ativamente desastroso.Respostas:
Certos recursos de idioma, como
geralmente não são úteis em um sistema em tempo real. Provavelmente, deve-se escolher um idioma sem esses recursos e tentar provar certas propriedades, como uso máximo de memória ou tempo máximo de resposta.
Quando um programa precisa ser executado continuamente, mas falhas curtas e não globais são aceitáveis, poderíamos usar uma estratégia do tipo Erlang. Erlang é uma linguagem de programação funcional e simultânea. Geralmente, um programa escrito em Erlang consiste em vários processos de trabalho que podem se comunicar (modelo de ator). Se um segmento de trabalho encontrar uma exceção, ele será reiniciado. Embora isso implique um curto tempo de inatividade, os outros atores podem continuar como de costume.
Para resumir isso: Em um programa robusto, várias partes são isoladas umas das outras e podem ser reiniciadas ou dimensionadas independentemente.
Então, basicamente, precisamos de um pedaço de código equivalente a isso:
além de uma maneira de terminar o loop. Esse loop conduziria cada segmento de trabalho.
Um problema ao ignorar erros por meio de um catch-all é que os invariantes do seu programa podem ter sido violados pela causa do erro e que as operações subsequentes podem ser inúteis. Uma boa solução para isso é não compartilhar dados entre trabalhadores independentes. Reiniciar um trabalhador reconstruirá todos os invariantes necessários. Isso significa que eles devem se comunicar de maneira diferente, por exemplo, através do envio de mensagens. O estado de um ator pode não fazer parte dos invariantes de outros atores.
Outro problema ao capturar muitas exceções é que nem todas as exceções são corrigíveis ao reiniciar, mesmo ao tomar essas precauções. Caso contrário, problemas difíceis, como ficar sem memória, podem ser resolvidos reiniciando. Mas uma reinicialização não ajudará você a recuperar a conectividade com a Internet quando um cabo físico foi retirado.
fonte
Para responder sua pergunta, é preciso entender o que são exceções e como elas funcionam.
Exceções geralmente são lançadas quando esses erros ocorrem, onde a assistência do usuário é necessária. Nesses casos, não importa quanto tempo leva para relaxar a pilha e manipular a exceção.
Sem manipuladores de captura, o programa interrompe a execução. Dependendo da sua configuração e requisitos, pode ser aceitável.
Nos seus casos específicos:
Isso significa que, em ambos os casos, pode fazer sentido usar exceções, com mais cuidado em um programa de RT para indicar apenas problemas sérios onde não é possível continuar a execução.
fonte
Parece que há um problema aqui, na medida em que as exceções não estão sendo tratadas adequadamente. Capturar exceções no ponto apropriado e tomar as medidas adequadas (dependendo do tipo de exceção) manterá o serviço em execução de uma maneira muito mais confiável.
Se o serviço precisar continuar, presumivelmente é importante que esteja funcionando conforme o esperado. Como exemplo, se um programa que controla interruptores ferroviários lança uma exceção, isso pode indicar que há um problema na comunicação com sensores relacionados à segurança. Se você capturar a exceção base e continuar, o serviço poderá ser executado, mas poderá não funcionar como planejado, levando ao desastre.
Como alternativa, se você capturar a exceção lançada quando houver uma falha de comunicação com o sensor e lidar com ela adequadamente (por exemplo, parar os trens na área afetada), seu serviço estará funcionando e você não matou ninguém.
Portanto, como eu entendo a pergunta, sugiro que, em primeira instância, você inclua um tratamento de exceção mais específico em vez de remover os manipuladores do tipo de exceção base.
fonte
Com relação ao ponto 2: não use C #. Não é uma linguagem em tempo real e você vai se machucar se você tentar usá-lo como tal.
Para o ponto 1: você pode seguir o caminho errado: deixe travar e reinicie
fonte
Declaimer: são apenas pensamentos, não tenho experiência.
Eu acho que um programa que atenda aos requisitos do segundo exemplo deve ser extremamente modular . Conseqüentemente, os módulos poderão ser reiniciados, sem desestabilizar o sistema.
Por exemplo, um objeto, na falta de uma afirmação de estado interno, deve poder ser destruído e recriado, notificando no processo todos os seus consumidores e fornecedores. Mais concretamente, se o programa estiver controlando os interruptores da ferrovia e falhar em uma afirmação no ciclo de decisão, ele ainda poderá executar um módulo de emergência, que interrompe todos os trens envolvidos e aguarda a reinicialização do módulo principal de decisão.
Mais realisticamente, introduziríamos redundância - duplicação de hardware e software. Uma instância é conectada ao sistema controlado e a outra é de execução livre. Se um erro for detectado, os sistemas serão trocados.
Um exemplo são dois processos na mesma máquina, que monitoram um ao outro e, se um é morto, o outro o gera novamente e desassocia seu PID pai de si mesmo.
fonte