System.Diagnostics.Process.Start comportamento estranho

votos
8

Eu estou escrevendo um aplicativo para iniciar e monitorar outros aplicativos em C #. Eu estou usando a classe System.Diagnostics.Process para iniciar aplicações e, em seguida, monitorar os aplicativos usando a propriedade Process.Responding para consultar o estado da aplicação a cada 100 milisecs. Eu uso Process.CloseMainWindow para parar a aplicação ou Process.Kill para matá-lo se ele não está respondendo.

Tenho notado um comportamento estranho onde às vezes o objeto de processo entra em um estado onde a propriedade responder sempre retorna true mesmo quando o processo subjacente trava em um loop e onde ele não responde a CloseMainWindow.

Uma maneira de reproduzi-lo é para pesquisar o direito de propriedade de responder depois de iniciar a instância do processo. Assim, por exemplo

_process.Start();
bool responding = _process.Responding;

vai reproduzir o estado de erro enquanto

_process.Start();
Thread.Sleep(1000);
bool responding = _process.Responding;

vai funcionar. Reduzir o período de sono para 500 irá apresentar o estado de erro novamente.

Algo em chamar _process.Responding muito rápido após o início parece impedir que o objeto de obter o manipulador de fila de mensagens janelas certas. Eu acho que eu preciso esperar para _process.Start Para terminar fazendo é trabalho assíncrona. Existe uma maneira melhor esperar para este do que chamar Thread.Sleep? Eu não estou muito confiante de que os 1000 ms sempre será suficiente.

Publicado 24/09/2008 em 08:58
fonte usuário
Em outras línguas...                            


4 respostas

votos
8

Agora, eu preciso verificar isso mais tarde, mas estou certo de que é um método que conta a thread para esperar até que ele está pronto para entrada. Você está monitorando apenas processos GUI?

Não é Process.WaitForInputIdle de qualquer ajuda para você? Ou estou faltando o ponto? :)

Atualizar

Na sequência de um bate-papo no Twitter (ou Piu-Piu?) Com Mendelt eu pensei que deveria atualizar a minha resposta para que a comunidade está plenamente consciente ..

  • WaitForInputIdle só irá funcionar em aplicações que têm uma GUI.
  • Você especifica o tempo de espera, e o método retorna um booleano se o processo atinge um estado ocioso dentro desse prazo, você pode, obviamente, usar isso para loop se necessário, ou manipular conforme apropriado.

Espero que ajude :)

Respondeu 24/09/2008 em 09:19
fonte usuário

votos
4

Eu acho que pode ser melhor para melhorar a verificação de _process.Responding para que você só tentar parar / matar o processo se a propriedade Respondendo retorna false por mais de 5 segundos (por exemplo).

Eu acho que você pode achar que, muitas vezes, os pedidos podem ser "não responde" por uma fração de segundo, enquanto eles estão fazendo um processamento mais intensivo.

Eu acredito que uma abordagem mais branda irá funcionar melhor, permitindo um processo para ser "não responde" por um curto período de tempo, somente a tomar medidas se for repetidamente "não responde" por alguns segundos (ou o tempo que você quiser).

Nota adicional: A documentação Microsoft indica que a propriedade Respondendo refere-se especificamente à interface do usuário, e é por isso um processo recém-iniciado não pode ter é UI responder imediatamente.

Respondeu 24/09/2008 em 09:08
fonte usuário

votos
3

Obrigado pelas respostas. este

_process.Start();
_process.WaitForInputIdle();

Parece resolver o problema. Ainda é estranho, porque responder e WaitForInputIdle ambos devem estar usando a mesma chamada Win32 API debaixo das cobertas.

Alguns mais informação de fundo
aplicações GUI tem uma janela principal com uma fila de mensagens. Responder e WaitForInputIdle trabalhar, verificando se o processo ainda processa as mensagens deste fila de mensagens. É por isso que eles só trabalham com aplicações GUI. De alguma forma, parece que a chamada Respondendo interfere muito rápido com a obtenção do Processo de obtenção de um identificador para essa fila mensagem. Chamando WaitForInputIdle parece resolver esse problema.

Eu vou ter que mergulhar no refletor para ver se consigo dar sentido a isso.

atualizar
Parece que recuperar o identificador de janela associado com o processo apenas depois de começar é suficiente para desencadear o comportamento estranho. Como isso:

_process.Start();
IntPtr mainWindow = _process.MainWindowHandle;

Eu verifiquei com refletor e é isso que faz Respondendo debaixo das cobertas. Parece que se você começar a MainWindowHandle muito cedo você começa a errada e ele usa esse identificador errado para o resto da vida útil do processo ou até que você chamar Refresh ();

atualização
Chamando WaitForInputIdle () só resolve o problema por algum tempo. Chamando Atualizar toda vez que () você lê a propriedade Respondendo parece funcionar melhor.

Respondeu 24/09/2008 em 10:08
fonte usuário

votos
1

Eu também notei que em um projeto de cerca de 2 anos. Liguei .Refresh () antes de solicitar certos valores prop. Foi uma abordagem de tentativa e erro para encontrar quando eu precisava chamar .Refresh ().

Respondeu 18/10/2008 em 02:50
fonte usuário

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more