Monday 23 April 2018

Processo outputdatareceived waitforexit


Herança múltipla.


Derivado de muitas coisas.


O processo Async OutputDataReceived / ErrorDataReceived tem uma falha ao lidar com prompts.


Classe System. Diagnostics. Process - Parte 2.


Na Parte 1, discuti o problema em que usando o redirecionamento stdout / stderr e lendo-os de forma síncrona, o buffer de saída pode ficar cheio e bloquear o processo filho na próxima "gravação". Em seguida, ocorre um impasse porque o processo pai está aguardando que a criança saia antes de ler dados do buffer, a criança está bloqueando a gravação porque o buffer está cheio e, portanto, o impasse. A resposta é simples & # 8211; é melhor usar o método assíncrono de leitura de dados de stdout / stderr. Esta questão é previsível e foi minha mágoa.


Não sou eu, é você.


Eu me deparo com outra questão, que parecia o mesmo impasse, onde uma má pressuposição na implementação da classe Processo da Microsoft causou um tipo diferente de impasse entre os processos pai e filho. Eu achei quando meu processo filho me levou a afirmar a atividade solicitada, veja a Figura 1 para um exemplo.


O prompt terminou sem uma nova linha, deixando o cursor no final do prompt (o que faz sentido, por que o cursor seria configurado sob o prompt e não ao lado dele na tela). Veja a Figura 2, por exemplo, o código desse prompt.


O meu processo pai foi codificado para inspecionar os dados de stdout recebidos de forma assíncrona, procurando o prompt. Se / quando o prompt foi recebido, o processo pai emitiria uma resposta ao stdin do processo filho. Veja a Figura 3.


No entanto, quando executo meu processo pai e o processo filho enviou o prompt, o texto nunca veio no evento OutputDataReceived ... e meu processo pai estava sentado na linha p. WaitForExit () para sempre ... O processo Child estava aguardando uma resposta que nunca veio dos pais, e estávamos mais uma vez em um impasse, desta vez eu não era eu ... O problema não estava no meu código.


No NewLine, no DataReceivedEvent ...


Comecei a depurar e assistir os eventos OutputDataReceived e comecei a mudar o código de processo filho de várias maneiras. A alteração pequena abaixo causou o evento OutputDataReceived para disparar com o prompt de texto, veja a Figura 4.


De alguns outros testes, parece que o evento OutputDataReceived é acionado somente quando um NewLine está na saída do processo filho. Um prompt sem um NewLine não dispararia o evento OutputDataReceived e, portanto, o processo pai não obteve o prompt e não pode responder. Impasse!


Implementando minha própria leitura assíncrona de stdout / stderr.


Eu preciso ler prompts de um processo filho que não é meu código, mas um aplicativo de consola de terceiros, então, finalmente, eu precisava receber prompts com NewLines. Resolver o problema exigiu que eu implementei minha própria classe Async IO para ler o processo stdout / stderror.


Eu criei uma classe chamada StdStreamReader que lê um fluxo e desencadeia eventos basicamente semelhantes ao evento Processo OutputDataReceived, no entanto, ele não destrói uma NewLine para disparar um evento recebido de dados, mas em vez disso dispara assim que os dados são recebidos. Na Figura 5, destaquei as diferenças de código no código de processo Parent usando a nova classe de leitor.


O código para o StdStreamReader é bastante mundano, mas o resultado foi o esperado, veja a Figura 6.


Observe que "Sim" não foi exibido logo após o prompt - isso ocorre porque ele foi enviado diretamente para o processo filho stdin e não exibido.


Clique para o código fonte completo, que é fornecido "como está", sem garantia de qualquer tipo.


Compartilhar isso:


Relacionados.


Pós-navegação.


Deixe uma resposta Cancelar resposta.


Bom trabalho, esta é a solução exata que eu estava procurando. Obrigado por incluir seu código-fonte!


Agradeço um milhão, cara! Aparentemente, esta questão ainda é relevante após 4 anos. Me ajudou muito.


Usando Process. BeginOutputReadLine pode levar a linhas de stdout perdidas # 12219.


joelverhagen comentou 30 de setembro de 2018 e # 8226;


Ao escrever código que cria processos filho e precisa capturar stdout, descobri que as linhas de saída perdem a seguinte condição:


muito paralelismo. ProcessStartInfo. RedirectStandardOutput = true Process. OutputDataReceived + = CollectLines (ou seja, usando o fluxo assíncrono) Process. BeginOutputReadLine () Process. WaitForExit (int. MaxValue)


Observe que passar -1 (período de tempo infinito) para WaitForExit não faz com que as linhas desapareçam (com base em meus próprios testes).


Criei um pequeno aplicativo de demonstração para fazer isso. É repro na netlineapp1.0 e net45: processredirect. zip. Basta usar o dotnet run para experimentá-lo.


Dito isto, você pode capturar stdout usando Process. StandardOutput (que é um StreamReader). No entanto, para consumir isso de maneira assíncrona e segura você precisa usar threads / tarefas de fundo. Em outras palavras:


Acho que isso é um problema porque é muito fácil entrar nesta armadilha. Usar os eventos para capturar o resultado é muito conveniente, pois você não precisa se preocupar em criar threads ou tarefas de plano de fundo. Além disso, a internet recomenda esse método:


Eu apenas tentei isso no Windows, Framework 4.5 e Core (netcoreapp1.0). Além disso, toda essa informação está relacionada ao stdout, mas imagino que o stderr tem o mesmo problema. Minha informação de dotnet é:


joelverhagen comentou 30 de setembro de 2018.


Atualizei o aplicativo de teste para suportar sistemas que não sejam do Windows (usando o eco):


Os resultados são os mesmos para Windows, Linux e Mac OS X.


Use as propriedades StreamReader no Processo em vez de eventos, pois você pode perder a saída # 906.


stephentoub comentou 7 de outubro de 2018 e # 8226;


@joelverhagen, para melhor ou pior, o que você está vendo é um design documentado.


Esta sobrecarga garante que todo o processamento foi concluído, incluindo o tratamento de eventos assíncronos para saída padrão redirecionada. Você deve usar essa sobrecarga após uma chamada para a sobrecarga WaitForExit (Int32) quando a saída padrão foi redirecionada para manipuladores de eventos assíncronos.


E para Process. WaitForExit (Int32):


Quando a saída padrão foi redirecionada para manipuladores de eventos assíncronos, é possível que o processamento de saída não seja concluído quando esse método retornar. Para garantir que o tratamento de eventos assíncrono tenha sido concluído, chame a sobrecarga WaitForExit () que não leva nenhum parâmetro depois de receber uma verdade dessa sobrecarga.


Você pode ver aqui que o código explicitamente não aguarda a saída redirecionada para ser concluída se foi passado um tempo limite não-infinito:


Dito isto, não sei por que foi projetado desta forma.


Priya91 comentou 7 de dezembro de 2018.


@joelverhagen Usando WaitForExit sem tempo limite depois que a outra sobrecarga deve desbloqueá-lo, como indicado nos documentos. Ao fechar esta questão, reabra se for necessário assistência adicional.


&cópia de; 2018 GitHub, Inc. Termos Privacidade Segurança Status Ajuda.


Você não pode executar essa ação neste momento.


Você fez login com outra guia ou janela. Recarregue para atualizar sua sessão. Você se separou em outra guia ou janela. Recarregue para atualizar sua sessão.


Processo . Evento OutputDataReceived.


A documentação de referência da API tem uma nova casa. Visite o navegador da API no docs. microsoft para ver a nova experiência.


Ocorre cada vez que um aplicativo grava uma linha em seu fluxo de saída StandardOutput redirecionado.


Assembly: System (no System. dll)


O evento OutputDataReceived indica que o Processo associado escreveu uma linha, terminando com um caractere de nova linha, ao fluxo de saída StandardOutput redirecionado.


O evento está habilitado durante operações de leitura assíncronas no StandardOutput. Para iniciar operações de leitura assíncronas, você deve redirecionar o fluxo StandardOutput de um Processo, adicionar seu manipulador de eventos ao evento OutputDataReceived e chamar BeginOutputReadLine. Posteriormente, o evento OutputDataReceived atende cada vez que o processo escreve uma linha para o fluxo de StandardOutput redirecionado, até o processo sair ou chama CancelOutputLit.


O aplicativo que está processando a saída assíncrona deve chamar o método WaitForExit para garantir que o buffer de saída tenha sido liberado.


O exemplo a seguir ilustra como executar operações de leitura assíncronas no fluxo do StandardOutput redirecionado do comando ipconfig.


O exemplo cria um delegado de evento para o manipulador de eventos OutputHandler e o associa com o evento OutputDataReceived. O manipulador de eventos recebe linhas de texto do fluxo de StandardOutput redirecionado, formata o texto e o salva em uma seqüência de saída que é mostrada mais tarde na janela do console do exemplo.


para uma confiança total para o chamador imediato. Este membro não pode ser usado por código parcialmente confiável.


Processo . Evento OutputDataReceived.


Ocorre quando um aplicativo grava seu fluxo de saída StandardOutribuído redirecionado.


Assembly: System (no System. dll)


O evento OutputDataReceived indica que o Processo associado escreveu no fluxo de StandardOutput redirecionado.


O evento está habilitado durante operações de leitura assíncronas no StandardOutput. Para iniciar operações de leitura assíncronas, você deve redirecionar o fluxo StandardOutput de um Processo, adicionar seu manipulador de eventos ao evento OutputDataReceived e chamar BeginOutputReadLine. Posteriormente, o evento OutputDataReceived atende cada vez que o processo escreve uma linha para o fluxo de StandardOutput redirecionado, até o processo sair ou chama CancelOutputLit.


O aplicativo que está processando a saída assíncrona deve chamar o método WaitForExit () para garantir que o buffer de saída tenha sido liberado.


O exemplo a seguir ilustra como executar operações de leitura assíncronas no fluxo de StandardOutput redirecionado do comando de ordenação. O comando classificar é um aplicativo de console que lê e classifica a entrada de texto.


O exemplo cria um delegado de evento para o manipulador de eventos SortOutputHandler e o associa com o evento OutputDataReceived. O manipulador de eventos recebe linhas de texto do fluxo StandardOutput redirecionado, formata o texto e grava o texto na tela.


Estrutura.


Framework Client Profile.


LinkDemand.


para uma confiança total para o chamador imediato. Este membro não pode ser usado por código parcialmente confiável.


Windows 7, Windows Vista SP1 ou posterior, Windows XP SP3, Windows XP SP2 x64 Edition, Windows Server 2008 (Server Core não suportado), Windows Server 2008 R2 (Server Core suportado com SP1 ou posterior), Windows Server 2003 SP2.


O Framework não suporta todas as versões de todas as plataformas. Para obter uma lista das versões suportadas, consulte Requisitos do sistema Framework.


process. OutputDataReceived ainda dispara mesmo após o processo teminado. # 432.


suwatch comentou 6 de março de 2018.


O sintoma relacionado.


Isso tem a ver com a implementação do Processo e seu fluxo assíncrono de saída. O cenário é que nós iniciamos o processo e escutamos em OutputDataReceived para capturar seu stdout. Nós chamamos process. WaitForExit e assumimos que depois que ele retorna verdadeiro (processo de significado encerrado), não deve haver nenhum evento mais disparado por OutputDataReceived.


Usando a reflexão, isso acaba por ser verdade se esperamos com -1 timeout (aguardará this. error. WaitUtilEOF () aka buffer to flush). Nosso intervalo de espera de implementação (5s) para permitir o gerenciamento ocioso. Essa espera pode retornar verdadeira mesmo que o OutputDataReceived ainda tenha saída pendente.


A saída esquerda foi disparada depois de nos fazer escrever para o mesmo registro xml como o segmento principal (assumindo que o processo foi concluído). O log xml fica corrompido como resultado da gravação simultânea.


conserte # 432 para aguardar a saída do processo # 433.


HenrikFrystykNielsen adicionou um compromisso a HenrikFrystykNielsen / kudu que referenciou esta questão 12 de março de 2018.


&cópia de; 2018 GitHub, Inc. Termos Privacidade Segurança Status Ajuda.


Você não pode executar essa ação neste momento.


Você fez login com outra guia ou janela. Recarregue para atualizar sua sessão. Você se separou em outra guia ou janela. Recarregue para atualizar sua sessão.

No comments:

Post a Comment