Observo que ninguém mencionou em suas respostas a esta velha questão que liberar um bloqueio em uma exceção é uma coisa incrivelmente perigosa de se fazer. Sim, as instruções de bloqueio em C # têm semântica "finalmente"; quando o controle sai do bloqueio normal ou anormalmente, o bloqueio é liberado. Vocês todos estão falando sobre isso como se fosse uma coisa boa, mas é uma coisa ruim! A coisa certa a fazer se você tiver uma região bloqueada que lança uma exceção não tratada é encerrar o processo doente imediatamente antes que destrua mais dados do usuário , e não liberar o bloqueio e continuar .
Veja desta forma: suponha que você tenha um banheiro com uma fechadura na porta e uma fila de pessoas esperando do lado de fora. Uma bomba explodiu no banheiro, matando a pessoa lá dentro. Sua pergunta é "nessa situação, a fechadura será desbloqueada automaticamente para que a próxima pessoa possa entrar no banheiro?" Sim vai. Isso não é uma coisa boa. Uma bomba explodiu lá e matou alguém! O encanamento provavelmente está destruído, a casa não é mais estruturalmente sólida e pode haver outra bomba lá . A coisa certa a fazer é tirar todos o mais rápido possível e demolir a casa inteira.
Quero dizer, pense bem: se você bloqueou uma região do código para ler de uma estrutura de dados sem sofrer mutação em outro encadeamento e algo nessa estrutura de dados lançou uma exceção, as chances são boas de que é porque a estrutura de dados está corrompido . Os dados do usuário agora estão confusos; você não deseja tentar salvar os dados do usuário neste momento porque, então, estará salvando dados corrompidos . Basta encerrar o processo.
Se você bloqueou uma região do código para realizar uma mutação sem outro thread lendo o estado ao mesmo tempo, e a mutação é lançada, então se os dados não estavam corrompidos antes, com certeza está agora . Qual é exatamente o cenário contra o qual a fechadura deve proteger . Agora, o código que está esperando para ler esse estado receberá imediatamente acesso ao estado corrompido e provavelmente travará. Novamente, a coisa certa a fazer é encerrar o processo.
Não importa como você o faça, uma exceção dentro de uma fechadura é uma má notícia . A pergunta certa a fazer não é "meu bloqueio será limpo no caso de uma exceção?" A pergunta certa a se fazer é "como posso garantir que nunca haja uma exceção dentro de um bloqueio? E, se houver, como faço para estruturar meu programa para que as mutações sejam revertidas para o estado normal anterior?"