среда, 13 июня 2018 г.

O processo líquido waitforexit trava


o registro de walter.
. Escrevendo enquanto aprende.
Sexta-feira, 18 de novembro de 2018.
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:

processo waitforexit trava
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.

C # Hoje.
Deixe o # C # hoje!
Deixe o # C # hoje!
Como evitar deadlocks ao ler o console filho redirecionado no C # 2.
A leitura da saída da criança redirecionada parece ser uma tarefa fácil. Mas há desenvolvedores que lutam com o processo infantil pendurado por causa de bloqueios de leitura / leitura de console. E os deadlocks nunca são fáceis de investigar.
Consideremos um exemplo comum - um processo pai inicia um processo filho e lê toda a saída. Aqui está um exemplo de aplicação que pode simular o cenário.
O aplicativo pode ser executado em dois modos:
Processo principal - executa o processo filho e lê seu processo de saída infantil - imprime um pouco de saída.
Tudo funciona bem, mas consideremos um cenário em que o rendimento da criança é significativo maior.
Desta vez, o processo pai irá pendurar - é um impasse. Por quê? Vamos pensar o que o pai faz - primeiro ele configura o redirecionamento de saída do processo filho.
Em seguida, inicia o processo filho.
O passo consecutivo aguarda a conclusão do processo infantil.
E esse é o ponto onde o processo pai bloqueia com a criança. Por quê? O pai está aguardando que a criança termine e a criança tenha alguma dependência do pai também.
Primeiro, você precisa entender como o redirecionamento de saída funciona. Há um buffer criado para a saída. Quando a criança está escrevendo para o console, ele realmente está escrevendo para o buffer. Se a criança escreve muito, o buffer pode ficar cheio. Nesse caso, a criança trava no Console. Write até o buffer ter algum espaço.
O pai deve ler a saída da criança antes de esperar que a criança termine. Então, para corrigir o impasse, temos que trocar as seguintes linhas.
O código pai completo deve ser mostrado abaixo.
Observe que exatamente o mesmo problema pode acontecer com a saída de erro padrão (stderr). Além disso, um impasse semelhante pode acontecer com a escrita na entrada padrão da criança.
Basicamente você precisa ter muito cuidado e entender o que você está fazendo se quiser ler a entrada / saída da criança de forma síncrona.
Deixe um comentário Cancelar resposta.
2 pensamentos sobre & ldquo; Como evitar deadlocks ao ler o console filho redirecionado em C # & rdquo;
Venceu esse impasse ainda que o processo produza muito em stderr? Eu acho que é realmente seguro, você precisa usar os eventos em vez disso.
Correto, adicionei uma nota sobre o stderr.
Eu concordo que o manuseio assíncrono é uma maneira mais segura. I & # 8217; ll escrever uma postagem sobre isso também.

Первичная навигация.
Форум только для чтения.
Администраторы сделали этот форум доступным только для чтения. Новые беседы или комментарии не могут быть добавлены.
Processe hnags ao executar qualquer comando usando o & # 160; Process. Start ()
Porque se o Process. Start () for bem-sucedido, eu poderia começar a interrogar a saída.
O ManagementBaseObject retornado pelo InvokeMethod não contém o retorno de saída real pelo processo.
Eu acho que isso pode estar relacionado com o redirecionamento de saída / erro. Isso é feito de maneira sinônimo, então você não pode redirecionar os dois ao mesmo tempo. Para fazer isso, ele deve ser feito de forma assíncrona. (BeginOutputReadLine, BeginErrorReadLine)
& quot; O exemplo de código evita a condição de bloqueio executando operações de leitura assíncronas no fluxo StandardOutput. Um estado de impasse resulta se o processo pai chamar p. StandardOutput. ReadToEnd seguido de p. StandardError. ReadToEnd e o processo filho escreve texto suficiente para preencher o fluxo de erros. O processo pai aguardaria indefinidamente o processo filho para fechar o fluxo StandardOutput. O processo infantil esperaria indefinidamente para o pai ler o fluxo completo do StandardError.
Você pode usar operações de leitura assíncronas para evitar essas dependências e seu potencial de impasse. Alternativamente, você pode evitar a condição de bloqueio criando dois segmentos e lendo a saída de cada fluxo em um segmento separado. & Quot;
URL em VS2005 Documentação:
Você já descobriu esse problema? Estou inclinado a pensar que é um bug no material de personificação em 2.0. Se eu remover a representação, isso funciona bem. mesmo a re-direção da saída e erro. Mas no momento que você tenta executar o processo como outro usuário, o processo é iniciado, mas depois trava. Eu diria segurança, exceto que não existe um erro por si. O processo começa bem, mas depois trava. Se fosse segurança, pensaria que você nunca começaria o processo. Também é interessante porque o problema também entra em cascata através de processos. Por exemplo, eu tentei envolver minha chamada de personificação em outro exe para que eu pudesse iniciar o programa inicial (do ASP) sem nenhuma representação. A mesma coisa acontece; o processo trava. não o processo de invólucro. O processo dentro do invólucro que está sendo representado trava! Louco. Se você executar o wrapper exe como qualquer usuário, ele também funciona bem, então eu sei que o wrapper funciona em todos os contextos que não sejam asp.
Alguém encontrou a solução para este problema?
Aqui está um que funciona no modo de depuração no ASP (2.xxx),
mas não funciona no modo publicado: ajuda!
classe pública myClass.
string público strBalance = string. Empty;
string privado runProc (string args)
Process proc = new Process ();
string passwordPre = & quot; MyPassword & quot ;;
char [] passwordChars = passwordPre. ToCharArray ();
SecureString password = new SecureString ();
foreach (char c in passwordChars)
return strBalance; // Eu nunca chego aqui publicado, eu trabalho em depuração.
strBalance & # 43; = e. Data; // Eu nunca chegar aqui em publicado, eu trabalho em depuração.
Беседа заблокирована.
Администраторы заблокировали эту беседу. Новые комментарии не могут быть добавлены.
© Майкрософт (Microsoft), 2018. Корпорация Microsoft сохраняет за собой все права, связанные с материалами на этом сайте.

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.

Комментариев нет:

Отправить комментарий