Por um erro de RaceOnRCWCleanup ao fechar um formulário com o controle WebBrowser nele?
-
18-09-2019 - |
Pergunta
VS2008, .NET 2, VB.NET, XP ...
Eu tenho um formulário do Windows, com um controle WebBrowser e um botão Fechar, que apenas faz um Me.Close
. Do formulário cancelar botão está definido para o botão Fechar, para que eu possa bater ESC para fechar o formulário.
I definir a propriedade DocumentText
do controle WebBrowser no evento de carregamento, e os monitores HTML.
A execução do aplicativo a partir do Visual Studio, se eu clicar no botão Fechar, o fechamento do formulário com nenhum erro.
Se eu acertar o botão ESC I get
RaceOnRCWCleanup foi detectado Mensagem: Uma tentativa foi feita para libertar um RCW que está em uso. o RCW está em uso na linha activa ou outro segmento. A tentativa de um livre em uso RCW pode causar corrupção ou perda de dados.
Se eu executar o aplicativo fora VS, recebo nenhum erro.
Todas as ideias a) Por que o erro, e b) como prevenir ou suprimi-lo?
Muito obrigado antecipadamente.
Solução
Não é um erro, ele é um aviso. Produzido por um assistente Gerenciado depuração (MDA), uma extensão para o depurador para código gerenciado, que pensa que está vendo algo errado em seu código. O sapato se encaixa. Você está usando um RCW, WebBrowser é um controle COM. Você está matando o RCW, você está fechando seu formulário. O MDA passos no sistema porque ele pensa que está vendo o navegador em uso e ser morto antes que a solicitação seja concluída. Que normalmente só fazem sentido se você estiver usando um fio em seu código.
E você? Se não, não perca o sono por isso. COM usa contagem de referência, notório por não ser capaz de resolver referências circulares.
Ok, eu tenho um repro para isso, habilitado pelos comentários. Sim, esta é desencadeada por propriedade CancelButton do formulário ou a propriedade DialogResult do botão. Isso acontece quando a WB tem o foco, ele vê o pressione a tecla Escape. Parte do encanamento ActiveX é dizer o recipiente sobre ele para que ele possa responder ao comando das teclas que devem ter um efeito colateral. combinações de teclas de atalho, Tab, Enter. E Escape. Se o botão, em seguida, fecha o formulário, o depurador vê o WB se eliminados, embora existam quadros de pilha ativos a partir do código RCW na pilha. O perigo é que isso pode causar um acidente quando os chamados retornos de código desde o componente COM foi lançado, não é incomum.
Vendo este acidente é bastante improvável, mas posso imaginar que isso poderia bombardear quando o segmento finalizador é executado pouco antes de retornos evento Click do botão. A solução alternativa para o MDA e o acidente potencial é para atrasar fechar o formulário até que o código ActiveX pára de funcionar. Elegantemente feito com Control.BeginInvoke (). Como esta:
private void CancelButton_Click(object sender, EventArgs e) {
this.BeginInvoke((MethodInvoker)delegate { this.Close(); });
}