Waitforexit nunca retorna
Obter através da App Store Leia esta publicação em nosso aplicativo!
O processo de linha de comando externo nunca retorna.
Estou usando o seguinte código vb para executar um aplicativo de linha de comando externo e ler sua saída:
Este código funcionou perfeitamente para várias aplicações. até agora. O problema é o seguinte: agora estou usando isso para executar "aapt. exe" (uma ferramenta que lhe dá informações sobre aplicativos Android do Apk) em um monte de arquivos, e o código fica preso (nunca retorna) no ponto que eu comentei mas apenas em 3 arquivos específicos de um total de 81.
É claro que meu primeiro pensamento foi que o programa externo estava falhando / ficando preso nesses arquivos particulares, mas eu testei o mesmo comando manualmente a partir de um prompt de comando e ele funciona perfeitamente! Além disso: adicionei um tempo limite ao código, como este:
E neste caso o processo retorna (obviamente), mas o que é interessante é que a saída está correta e completa! Isso implica que o programa externo está sendo executado corretamente até o final, então por que o processo não retorna por conta própria? Existe alguma maneira viável de depurar isso?
EDIT: Depois de horas de teste, cheguei à conclusão de que o problema está na opção "RedirectStandardOutput". Não importa qual ordem eu executo / leio, ele trava em algumas execuções. Eu não encontrei uma solução adequada para isso, eu implementei uma solução (horrível) em que desabilitei o redirecionamento de stdout e, em vez disso, apresentei o stdout para um arquivo e, imediatamente, leia novamente no meu código quando o processo termina (ele termina definitivamente deste modo pelo menos). Não é uma solução elegante, e eu ainda gostaria de chegar ao final disso, então deixo a questão aberta se alguém tiver melhores idéias do que as minhas.
Eu acho que você provavelmente só precisa chamar Dim ret = myOutput. ReadToEnd antes de proc. WaitForExit (). O MSDN avisa sobre um impasse de chamar WaitForExit () primeiro: "Uma condição de bloqueio pode resultar se o processo pai chama p. WaitForExit antes de p. StandardOutput. ReadToEnd e o processo filho grava texto suficiente para preencher o fluxo redirecionado. O processo pai aguardaria indefinidamente, para que o processo filho saia. O processo filho aguardaria indefinidamente para que o pai leia o fluxo de StandardOutput completo ". Então eu acho que esses arquivos de 3/81 só têm mais saída do que os outros.
Você tentou adicionar o parâmetro C ao final para que ele volte depois de sair. por exemplo. cmd / C "" abc. exe ""
Aqui "/ C" é importante, informa o prompt de comando para sair depois que ele for concluído.
Waitforexit nunca retorna
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.
o registro de walter.
. Escrevendo enquanto aprende.
Sexta-feira, 18 de novembro de 2011.
Process. WaitForExit (Int32) bloqueia o problema.
Como você pode ver, o código inicia um processo "cmd. exe" e passa para ele o comando que eu quero ser executado.
No código eu usei o comando ping - t 8.8.8.8 que, por causa da opção - t, pings o host sem parar. O que acontece? O processo "cmd. exe" juntamente com o comando ping - t nunca sai e nunca fecha o fluxo de stdout e, portanto, o nosso código trava no Output = process. StandardOutput. ReadToEnd (); linha, porque não pode ter sucesso em ler todo o fluxo.
O mesmo acontece também se um comando em um arquivo em lotes trava por qualquer motivo e, portanto, o código acima pode funcionar continuamente por anos e, em seguida, pendure de repente sem nenhum motivo aparente.
você pode enfrentar um impasse se o comando que você atribui a "cmd. exe" ou o processo que você está chamando preenche a saída padrão ou erro padrão. Isso porque nosso código não pode alcançar as linhas.
Na verdade, o processo filho (o comando ping ou um arquivo em lote ou o processo que estiver executando) não pode continuar se o nosso programa não ler os buffers preenchidos dos fluxos e isso não pode acontecer porque o código está pendurado na linha com o processo. WaitForExit () que aguardará para sempre que o projeto filho saia.
O tamanho padrão de ambos os fluxos é de 4096 bytes. Você pode testar esses dois tamanhos com esses arquivos em lote:
Waitforexit nunca retorna
Eu tenho o seguinte código na minha aplicação:
System. Diagnostics. Process proc = new System. Diagnostics. Process ();
Uma vez que eu chamo isso através de outra aplicação, o processo está pendurado.
Então eu dei um tempo de 5 segundos e agora funciona bem. Mas eu preciso encontrar uma maneira melhor de resolver esse problema, pois esse valor de tempo limite pode depender dos recursos do sistema e a quantidade de aplicativo de entrada deve ser processada.
Então, minha pergunta é se estamos criando um processo usando o System. Diagnostics, o sistema operacional cria um segmento separado e o faz como fio primário ou UI thread?
Ou está criando um fio CLR que é o mesmo que System. Threading. Thread?
Se usarmos Thread-pool para criar uma thread de trabalho, seria uma opção melhor?
O pool de threads usa o modo de programação do usuário?
Aprecie sua ajuda nisso.
Eu preciso saber disso, porque se o System. Diagnostics também criar um thread de fundo ou thread de trabalho, nenhum ponto criando um thread separado novamente, pois não haverá nenhuma alteração no final do dia.
Qual a diferença entre a implementação acima sobre a criação de uma linha de fundo?
Você está confundindo os tópicos internos e externos ao seu aplicativo. Se você usa WaitForExit no seu segmento UI. Isso bloqueará o segmento UI tornando-o insensível. Se isso é um problema, genere o novo processo no evento DoWork de um BackgroundWorker. Quando o processo for encerrado, o RunWorkerCompleteEvent será ativado, alertando seu segmento UI.
Marcado como resposta por Min Zhu pessoal contingente da Microsoft, Moderador segunda-feira, 18 de julho de 2011 3:10 AM.
Todas as respostas.
Esperando um evento com EnableRaisingEvents = false significa que você está usando WaitForExit como um temporizador. Defina-o para um valor apropriado.
Esperando um evento com EnableRaisingEvents = false significa que você está usando WaitForExit como um temporizador. Defina-o para um valor apropriado.
Eu atribuí 5000 como o valor e corrigiu o problema. Minha preocupação é que funcionará de forma semelhante em diferentes recursos do sistema, tamanho de conteúdo de entrada etc.?
O que acontecerá se o processo associado não sair ao final do intervalo?
O Windows não é um sistema operacional em tempo real, então qualquer temporizador dependerá do agendamento do sistema operacional. Supostamente, o System. Timers. Timer é o mais preciso.
& quot; o que acontecerá se o processo associado não sair ao final do intervalo? & quot; Você desativou esse recurso. Se é isso que você está tentando fazer, habilite-o. Se você não deseja bloquear o segmento que você usou para iniciar o processo, inicie-o a partir de um segmento de fundo. O BackgxroundWorker seria apropriado para isso.
Eu preciso saber disso, porque se o System. Diagnostics também criar um thread de fundo ou thread de trabalho, nenhum ponto criando um thread separado novamente, pois não haverá nenhuma alteração no final do dia.
Qual a diferença entre a implementação acima sobre a criação de uma linha de fundo?
Eu preciso saber disso, porque se o System. Diagnostics também criar um thread de fundo ou thread de trabalho, nenhum ponto criando um thread separado novamente, pois não haverá nenhuma alteração no final do dia.
Qual a diferença entre a implementação acima sobre a criação de uma linha de fundo?
Você está confundindo os tópicos internos e externos ao seu aplicativo. Se você usa WaitForExit no seu segmento UI. Isso bloqueará o segmento UI tornando-o insensível. Se isso é um problema, genere o novo processo no evento DoWork de um BackgroundWorker. Quando o processo for encerrado, o RunWorkerCompleteEvent será ativado, alertando seu segmento UI.
Marcado como resposta por Min Zhu pessoal contingente da Microsoft, Moderador segunda-feira, 18 de julho de 2011 3:10 AM.
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.
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.
o registro de walter.
. Escrevendo enquanto aprende.
Sexta-feira, 18 de novembro de 2011.
Process. WaitForExit (Int32) bloqueia o problema.
Como você pode ver, o código inicia um processo "cmd. exe" e passa para ele o comando que eu quero ser executado.
No código eu usei o comando ping - t 8.8.8.8 que, por causa da opção - t, pings o host sem parar. O que acontece? O processo "cmd. exe" juntamente com o comando ping - t nunca sai e nunca fecha o fluxo de stdout e, portanto, o nosso código trava no Output = process. StandardOutput. ReadToEnd (); linha, porque não pode ter sucesso em ler todo o fluxo.
O mesmo acontece também se um comando em um arquivo em lotes trava por qualquer motivo e, portanto, o código acima pode funcionar continuamente por anos e, em seguida, pendure de repente sem nenhum motivo aparente.
você pode enfrentar um impasse se o comando que você atribui a "cmd. exe" ou o processo que você está chamando preenche a saída padrão ou erro padrão. Isso porque nosso código não pode alcançar as linhas.
Na verdade, o processo filho (o comando ping ou um arquivo em lote ou o processo que estiver executando) não pode continuar se o nosso programa não ler os buffers preenchidos dos fluxos e isso não pode acontecer porque o código está pendurado na linha com o processo. WaitForExit () que aguardará para sempre que o projeto filho saia.
O tamanho padrão de ambos os fluxos é de 4096 bytes. Você pode testar esses dois tamanhos com esses arquivos em lote:
Comments
Post a Comment