Friday 2 March 2018

O processo waitforexit does not wait


Process. waitforexit não aguarda
Obter através da App Store Leia esta publicação em nosso aplicativo!
Por que Process. WaitForExit doesn & # 39; t wait?
Por que Process. WaitForExit não espera?
Mantém o loop e inicia o aplicativo novamente e novamente!
Trabalhou agora, não funcionava porque era assim clsProcess. WaitForExit (1000);
Este código está envolvido em um loop de tempo (verdadeiro) e não há declarações de quebra, lançamento ou retorno dentro do corpo do loop. Isso resultará em um loop infinito.
Se você quiser sair do loop uma vez que o WaitForExit tenha terminado, você precisa apresentar uma declaração de quebra para fazê-lo.
Verifique se (Process. GetProcessesByName ("ServerAPPFileManager"). Comprimento & gt; 0) não retorna falso.
Bem, é assim que você codificou. Está aguardando a saída, então na próxima declaração se inicia novamente. E, como Jared apontou, continua ficando sem nenhuma maneira de sair. então ele começa, espera que ele saia e depois comece novamente.

Process. waitforexit não aguarda
Obter através da App Store Leia esta publicação em nosso aplicativo!
Process. WaitForExit doesn & # 39; t retornam mesmo que Process. HasExited seja verdade.
Eu uso Process. Start para iniciar um arquivo em lote. O arquivo em lote usa o comando "INICIAR" para iniciar vários programas em paralelo e depois sai.
Uma vez que o arquivo em lote é feito Process. HasExited torna-se verdadeiro e Process. ExitCode contém o código de saída correto.
Mas quando chamo Process. WaitForExit (), ele trava / nunca retorna.
O código a seguir demonstra o problema. Ele cria um arquivo em lotes, o inicia e depois imprime:
Ele deve imprimir:
. mas nunca faz (mesmo que HasExited é verdadeiro e já temos um ExitCode).
Percebi que isso só ocorre quando o arquivo em lotes contém comandos "INICIAR" e quando a saída padrão e / ou o erro padrão são redirecionados.
Por que WaitForExit () nunca retorna?
Qual é o caminho certo para esperar que esse processo saia?
É seguro apenas pesquisar Process. HasExited ou isso pode resultar em outros problemas?
PS .: Eu notei que chamar WaitForExit (100000) com um tempo limite enorme (que definitivamente não expira) retorna imediatamente quando o processo sai. Wierd. Sem tempo limite, trava.
Isso parece ser um artefato (eu diria "bug") na implementação específica do tratamento assíncrono baseado em eventos do StandardOutput e do StandardError.
Percebi que, enquanto consegui reproduzir facilmente o seu problema, simplesmente executando o código que você forneceu (excelente exemplo de código, a propósito! :)), o processo realmente não foi suspenso indefinidamente. Em vez disso, ele retornou de WaitForExit () uma vez que ambos os processos filho que tinham sido iniciados já haviam saído.
Esta parece ser uma parte intencional da implementação da classe Process. Em particular, no método Process. WaitForExit (), uma vez que acabou de aguardar o processo, ele verifica se um leitor para stdout ou stderr foi criado; se assim for, e se o valor de tempo limite para a chamada WaitForExit () for "infinito" (ou seja, -1), o código realmente espera o fim do fluxo no (s) leitor (es).
Cada leitor respectivo é criado somente quando o método BeginOutputReadLine () ou BeginErrorReadLine () é chamado. Os fluxos stdout e stderr não estão fechados até que os processos filho tenham fechado. Então, esperando no final desses fluxos irá bloquear até que isso aconteça.
Que WaitForExit () deve se comportar de forma diferente, dependendo se um tenha chamado qualquer um dos métodos que iniciam a leitura baseada em eventos dos fluxos ou não, e especialmente porque a leitura desses fluxos diretamente não faz WaitForExit () se comportar desse jeito, cria uma inconsistência na API que torna muito mais difícil de entender e usar. Enquanto eu pessoalmente chamaria isso de bug, suponho que seja possível que o (s) implementador (es) da classe Process esteja ciente dessa inconsistência e criou de propósito.
Em qualquer caso, o trabalho seria ler StandardOutput e StandardError diretamente em vez de usar a parte baseada em eventos da API. (Embora, é claro, se o código de alguém aguardasse esses fluxos, verificaria o mesmo comportamento de bloqueio até que o filho fique próximo).
Por exemplo (C #, porque eu não sei F # bem o suficiente para tapar um exemplo de código como este juntos rapidamente :)):
Felizmente, o trabalho acima ou algo semelhante abordará o problema básico que você encontrou. Meus agradecimentos ao comentarista Niels Vorgaard Christensen por dirigir-me para as linhas problemáticas no método WaitForExit (), para que eu possa melhorar essa resposta.

Process. waitforexit não aguarda
Estou escrevendo um programa que inicia um número desconhecido de processos em sequência usando myProcess. Start () e myProcess. WaitForExit ().
O problema parece ser que alguns processos podem iniciar outros processos e depois sair, fazendo com que meu programa continue sem o processo iniciado, na verdade, completando sua tarefa. Existe alguma maneira de monitorar esses "subprocessos"?
Desde já, obrigado.
Editar: depois de algum teste adicional, descobri que o mesmo problema ocorre quando, por exemplo, iniciando o Winword. exe. WaitForExit simplesmente não funciona com alguns aplicativos.
Tom escreveu sobre o mesmo problema neste tópico.
mas ficou satisfeito quando trabalhou em um computador diferente.
Parece que um "WINWORD. EXE" - processo já está sendo executado na minha máquina. Possivelmente porque uso o Word como editor (?). Fechar isso antes de executar o meu programa (que está configurado para iniciar a palavra e aguardar a saída) & quot; resolve & quot; o problema. No entanto, não posso assumir que a winword não está sendo executada quando o meu programa é iniciado.
Não, não há muito que você possa fazer de forma confiável. O problema é que, no momento em que você chama WaitForExit, o aplicativo talvez já tenha iniciado outro aplicativo e tenha saído; Não há como saber se essa aplicação gerou outras pessoas nesse ponto.
É a natureza do Process. Start. Você não está descobrindo que WaitForExit espera indefinidamente porque o processo veio e foi antes de você chamou você?
Bem, ele cria um novo processo, é tão rápido que não pode aparecer no Process Explorer. Tudo Process. Start faz é pedir que o processo comece; Não há mais nada que o novo processo seja necessário para fazer. Se não quiser ficar na memória, essa é sua escolha. Não há nada que você possa fazer sobre isso, infelizmente.
Algumas aplicações sempre iniciam um novo processo. Quando você abre um arquivo Visual Studio SLN, por exemplo, ele sempre inicia dois processos. Existe uma pequena aplicação que verifica o tipo do arquivo SLN e, em seguida, abre uma versão apropriada do Visual Studio porque você só pode associar um aplicativo por extensão.
A outra questão é que algumas aplicações podem lidar com vários documentos de cada vez, o que significa que eles geralmente reutilizam os processos existentes. Em casos como este, se o processo for reutilizado porque um documento já estava aberto, isso significa que o documento que você abriu com Process. Start pode ser fechado, mas o processo de hospedagem ainda está sendo executado (atendendo o documento original) o que significa que você nunca pode Diga quando o processo que foi reutilizado quando você chamou Process. Start é feito com o documento que foi aberto com seu Process. Start.
Se você estiver olhando para integrar algum tipo de solução do WinWord, eu sugiro usar a automação. Consulte msdn. microsoft/newsgroups/default. aspx? dg=microsoft. public. officedev&lang=en&cr=US para discussões sobre a automação de produtos do Office.
Todas as respostas.
Não, não há muito que você possa fazer de forma confiável. O problema é que, no momento em que você chama WaitForExit, o aplicativo talvez já tenha iniciado outro aplicativo e tenha saído; Não há como saber se essa aplicação gerou outras pessoas nesse ponto.
É a natureza do Process. Start. Você não está descobrindo que WaitForExit espera indefinidamente porque o processo veio e foi antes de você chamou você?
Não, espero que essa situação não ocorra (É mesmo possível? Não pensei nisso antes). De qualquer forma, isso responde claramente a um dos problemas. Obrigado.
Mas deve haver uma súbita questão sobre o início do winword. exe (e similar) que. Nenhum processo extra é mostrado no taskmanager (mas ainda a palavra aparece). Quero forçar a criação de um novo processo que eu possa controlar.
Bem, ele cria um novo processo, é tão rápido que não pode aparecer no Process Explorer. Tudo Process. Start faz é pedir que o processo comece; Não há mais nada que o novo processo seja necessário para fazer. Se não quiser ficar na memória, essa é sua escolha. Não há nada que você possa fazer sobre isso, infelizmente.
Algumas aplicações sempre iniciam um novo processo. Quando você abre um arquivo Visual Studio SLN, por exemplo, ele sempre inicia dois processos. Existe uma pequena aplicação que verifica o tipo do arquivo SLN e, em seguida, abre uma versão apropriada do Visual Studio porque você só pode associar um aplicativo por extensão.
A outra questão é que algumas aplicações podem lidar com vários documentos de cada vez, o que significa que eles geralmente reutilizam os processos existentes. Em casos como este, se o processo for reutilizado porque um documento já estava aberto, isso significa que o documento que você abriu com Process. Start pode ser fechado, mas o processo de hospedagem ainda está sendo executado (atendendo o documento original) o que significa que você nunca pode Diga quando o processo que foi reutilizado quando você chamou Process. Start é feito com o documento que foi aberto com seu Process. Start.
Se você estiver olhando para integrar algum tipo de solução do WinWord, eu sugiro usar a automação. Consulte msdn. microsoft/newsgroups/default. aspx? dg=microsoft. public. officedev&lang=en&cr=US para discussões sobre a automação de produtos do Office.
Winword era apenas um exemplo. Mesmo que a sua resposta não fosse o que eu esperava, explica como tudo funciona e o comportamento que posso esperar.
Me salve muito tempo procurando algo que não exista. Obrigado.
A Microsoft está conduzindo uma pesquisa on-line para entender sua opinião sobre o site da Msdn. Se você optar por participar, a pesquisa on-line será apresentada quando você deixar o site Msdn.

Exemplo de uso.
Resolvi assim:
Eu redirecionava a entrada, a saída e o erro e administrai a leitura dos fluxos de saída e erro. Esta solução funciona para o SDK 7- 8.1, tanto para o Windows 7 como para o Windows 8.
Eu tentei fazer uma aula que resolva seu problema usando a leitura de fluxo assíncrono, levando em conta Mark Byers, Rob, Stevejay responde. Ao fazê-lo, percebi que existe um erro relacionado à leitura assíncrona do fluxo de saída do processo.
Você não pode fazer isso:
Você receberá System. InvalidOperationException: StandardOut não foi redirecionado ou o processo ainda não começou.
Então, você deve iniciar a saída assíncrona lida após o processo ser iniciado:
Fazendo isso, faça uma condição de corrida porque o fluxo de saída pode receber dados antes de configurá-lo como assíncrono:
Então algumas pessoas podem dizer que você só precisa ler o fluxo antes de configurá-lo como assíncrono. Mas o mesmo problema ocorre. Haverá uma condição de corrida entre a leitura síncrona e configurará o fluxo em modo assíncrono.
Não há como conseguir uma leitura assíncrona segura de um fluxo de saída de um processo na forma real "Processo" e "ProcessStartInfo" foi projetado.
Você provavelmente está melhor usando a leitura assíncrona, como sugerido por outros usuários para o seu caso. Mas você deve estar ciente de que você pode perder algumas informações devido à condição de corrida.
Nenhuma das respostas acima está fazendo o trabalho.
A solução Rob trava e a solução 'Mark Byers' obtém a exceção descarta. (Eu tentei as "soluções" das outras respostas).
Então eu decidi sugerir outra solução:
Este código é depurado e funciona perfeitamente.
Eu acho que isso é uma abordagem simples e melhor (não precisamos do AutoResetEvent):
Eu estava tendo o mesmo problema, mas a razão era diferente. No entanto, isso aconteceria no Windows 8, mas não no Windows 7. A seguinte linha parece ter causado o problema.
A solução era NÃO desativar UseShellExecute. Agora recebi uma janela popup do Shell, que é indesejável, mas muito melhor do que o programa esperando que nada de particular aconteça. Então eu adicionei o seguinte trabalho para isso:
Agora, o único problema que me incomoda é o porquê isso está acontecendo no Windows 8, em primeiro lugar.
Introdução.
A resposta atualmente aceita não funciona (lança exceção) e há muitas soluções alternativas, mas nenhum código completo. Isso é, obviamente, desperdiçando muito tempo das pessoas porque esta é uma questão popular.
Combinando a resposta de Mark Byers e a resposta de Karol Tyl, escrevi um código completo baseado em como eu quero usar o método Process. Start.
Eu usei-o para criar um diálogo de progresso em torno dos comandos git. É assim que eu usei isso:
Em teoria, você também pode combinar stdout e stderr, mas não testei isso.
Eu sei que isso é velho, mas, depois de ler toda essa página, nenhuma das soluções estava funcionando para mim, embora eu não tentei Muhammad Rehan porque o código era um pouco difícil de seguir, embora eu acho que ele estava no caminho certo . Quando eu digo que não funcionou, isso não é inteiramente verdade, às vezes funcionaria bem, acho que é algo a ver com a duração da saída antes de uma marca EOF.
De qualquer forma, a solução que funcionou para mim era usar diferentes threads para ler o StandardOutput e StandardError e escrever as mensagens.
Espero que isso ajude alguém, que pensou que isso poderia ser tão difícil!
As outras soluções (incluindo o EM0) ainda estão bloqueadas para o meu aplicativo, devido a tempos de espera internos e ao uso de StandardOutput e StandardError pela aplicação gerada. Aqui está o que funcionou para mim:
Editar: inicialização adicionada de StartInfo para codificar a amostra.
Este post talvez esteja desactualizado, mas descobri a principal causa por que normalmente ele trava é devido ao excesso de pilha para o redirectStandardoutput ou se você tem redirectStandarderror.
Como os dados de saída ou os dados de erro são grandes, isso causará um tempo de espera, pois ele ainda está processando por tempo indefinido.

No comments:

Post a Comment