Esperando um processo com tempo limite em.
Na mesma linha da minha última publicação, podemos querer ser mais inteligentes sobre o lançamento de um processo e aguardamos a saída.
Particularmente, se esse processo for parte de um sistema crítico, como seu processo de compilação, você não quer que um processo suspenso seja capaz de fazer com que seu sistema de compilação inteiro pare de morrer nas suas faixas.
Felizmente, o Processo tem uma sobrecarga de WaitForExit que leva um tempo limite inteiro e retorna um booleano - verdadeiro se o processo for encerrado ou falso se o processo não acontecesse.
Usando esta função, podemos escrever um método como este:
Neste trecho, OutputDataReceived é um evento que dispara quando o processo grava dados em saída padrão e sinais BeginOutputReadLine para que configuramos nosso evento e estamos prontos para começar a ouvir a saída do processo.
Usar o formulário de evento neste caso significa que não precisamos ter o texto de saída completo do processo na memória em nenhum momento. À medida que o processo escreve uma linha de texto, teremos apenas essa linha na memória, e isso será coletado por lixo depois de atualizar nosso contador.
Há dois "gotcha" s neste trecho, no entanto.
O primeiro é process. Kill (). Esta é uma condição de corrida clássica - entre o tempo em que nosso processo retorna de process. WaitForExit () e invoca processo. Kill (), o processo de destino pode sair. Nesse caso, o MSDN afirma que, se você chamar. Kill () em um processo que já saiu, você receberá uma InvalidOperationException.
Podemos corrigir isso, manipulando a exceção, assim:
O segundo "gotcha" é muito sutil, e você provavelmente não o achará até que a função não retorne o resultado esperado, ou até se sentar e ler toda a página de documentação para Process. WaitForExit (int). O MDSN afirma que:
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.
Nesse caso, é possível que nossa função GetNumOutputChars devolva um valor que contenha menos caracteres do que a saída real do processo, a menos que chamemos WaitForExit () novamente.
Com isso em mente, nossa função de segurança final agora se parece com isto:
Processo waitforexit kill
Obter através da App Store Leia esta publicação em nosso aplicativo!
Process. kill () termina o WaitForExit () (sem limite de tempo)
Eu tenho um processo que é executado em segundo plano e tem WaitForExit (), uma vez que a duração pode variar e preciso aguardar até terminar. Em ocasiões, eu preciso terminar antes de completar e desencadeio o comando. Kill () através de um evento de classe. A propriedade. HasExited muda para true, mas o código nunca passa a linha WaitForExit ().
Meu processo lança um cliente de transferência de arquivos baseado em java e executa uma transferência. O processo aparece no gerenciador de tarefas e Kill () não termina. Como eu realmente não me importo com o encerramento do processo, mas preciso do meu programa para a próxima "tarefa", adicionei Close () logo após Kill (), que libera o WaitForExit e deixa meu código "mover-se". Terminar o processo cedo será uma ocorrência rara no meu aplicativo, mas ainda preciso que ele funcione, então essa implementação terá que fazer.
WaitForExit é uma chamada direta para o sistema operacional para aguardar a sinalização do processar. Quando um processo termina, o WaitForExit será concluído. Kill é uma chamada direta para TerminateProcess, que é uma matança sem perguntas. Se usado corretamente WaitForExit retornará depois que Kill for concluída.
Então, há algum outro erro em seu código. Crie uma reprodução mais simples e você verá o problema desaparecer. O bug está escondido na complexidade do seu código.
Ou, WaitForExit retornou, mas você não percebeu. Ou, Kill nunca foi executado ou falhou. Mais uma vez, a simplificação do código revelará o problema. Você pode trazer para uma reprografia de 5 linhas? Eu duvido que você possa, mas vou olhar novamente se você fizer isso.
Nos comentários, você especificou que o kill ping funciona, mas matar seu processo especial não. A causa disso geralmente não é cancelável IO. O kernel do Windows mantém processos ao redor até que todos os IO sejam feitos. A boa notícia é que o processo irá morrer eventualmente e nenhum código será executado depois que Kill tenha retornado. A má notícia é que a limpeza de recursos não está totalmente concluída.
Matar um processo?
Estou usando um objeto BackgroundWorker para iniciar um processo, o seguinte é dentro do meu evento BackgroundWorker. DoWork:
A principal razão pela qual eu preciso matar o processo é excluir arquivos temporários usados pelo processo que não pode ser excluído enquanto o processo está sendo executado.
Quando a depuração descobriu esse processo. Kill () não parece estar fazendo nada. A próxima linha process. WaitForExit () apenas aguarda até que o processo execute seus procedimentos normais.
Para meus propósitos de limpeza de recursos, meu código parece funcionar bem. Mas, idealmente, eu quero poder controlar a vida útil do processo. Isso poderia ter alguma coisa a ver com as permissões de administrador? Alguma ideia?
O processo que você está executando tem uma janela (ou uma bomba de mensagem?). Se assim for, use. CloseMainWindow () em vez de. Kill ()..Kill deve encerrar o processo, mas acho que isso requer privilégios de administrador, enquanto eu não acho que o CloseMainWindow () o exige.
Há uma diferença distinta entre os dois - Kill () encerra instantaneamente o processo e não faz nenhuma limpeza (abrir as alças de arquivos não serão fechadas, etc.) semelhante a matar um processo no gerenciador de tarefas, enquanto que CloseMainWindow () envia uma solicitação para o bomba de mensagem do programa para fechar. Supondo que não há nenhum manipulador de evento on_close no processo para evitar que ele feche (como na palavra quando ele pergunta se você deseja salvar), então ele deve fechar de forma ordenada.
O processo que você está executando tem uma janela (ou uma bomba de mensagem?). Se assim for, use. CloseMainWindow () em vez de. Kill ()..Kill deve encerrar o processo, mas acho que isso requer privilégios de administrador, enquanto eu não acho que o CloseMainWindow () o exige.
Há uma diferença distinta entre os dois - Kill () encerra instantaneamente o processo e não faz nenhuma limpeza (abrir as alças de arquivos não serão fechadas, etc.) semelhante a matar um processo no gerenciador de tarefas, enquanto que CloseMainWindow () envia uma solicitação para o bomba de mensagem do programa para fechar. Supondo que não há nenhum manipulador de evento on_close no processo para evitar que ele feche (como na palavra quando ele pergunta se você deseja salvar), então ele deve fechar de forma ordenada.
O processo não tem uma janela ou qualquer tipo de interface. Eu já tentei usar o CloseMainWindow () no lugar de Kill () e eu obtenho o mesmo resultado. O processo não é morto.
Tente executá-lo como administrador e me avise o que acontece.
Tente executá-lo como administrador e me avise o que acontece.
Eu descobri o problema, mas ainda preciso de uma solução.
O processo está criando outra instância de si mesmo (então há 2 instâncias do processo em execução). Quando chamo process. Kill (), um deles é morto, e um deles ainda está em execução, fazendo com que process. WaitForExit () aguarde.
A única solução que eu consigo pensar é pesquisar todos os processos em execução por nome e matá-lo desse jeito ... o que não soa ideal.
O deve ser de outra maneira, especialmente considerando o fato de todas as instâncias do processo serem mortas quando meu aplicativo sai.
Você pode obter todos os PID criados por um processo pai usando objetos de gerenciamento do Windows (usando recursão):
Você pode obter o ID do proc pai com o membro process. ID. Dê um giro e me avise se isso funciona. Isso é efetivamente como 'Kill Process Tree' funciona no taskmanager.
Editado há 5 anos por skatamatic: n / a.
Você pode obter todos os PID criados por um processo pai usando objetos de gerenciamento do Windows (usando recursão):
Você pode obter o ID do proc pai com o membro process. ID. Dê um giro e me avise se isso funciona. Isso é efetivamente como 'Kill Process Tree' funciona no taskmanager.
Trabalhou perfeitamente. Muito obrigado.
Tive um problema semelhante com interoperabilidade e tive que forçar um GC.
Não é possível obter o título do processo? - 5 respostas c ++ - 1 resposta Ajuda com script Perl que gera muitos processos filho - 3 respostas Como diferenciar entre um processo pré-existente e um que comecei - 7 respostas diferença entre comando - 4 respostas A aplicação permanece em processo mesmo após a saída O botão é clicado - 3 respostas Como matar um processo filho travado no Windows - 2 respostas Problemas de tubulação em C - 9 respostas incapazes de copiar arquivo & obj \ release & quot; para & quot; bin \ release & quot ;. O processo não pode acessar o fil - 4 respostas mata um processo - 5 respostas Precisa de ajuda com o meu shell - 7 respostas matando um processo em python - 9 respostas [Python] Como matar um processo específico iniciado por subprocesso. Popen - 14 respostas Como pode Eu mato um processo específico? - 10 respostas Problema C ++ no Linux - 33 respostas Problema com C no Linux - 6 respostas Process Killer - 11 respostas Problema Litte - 3 respostas Projeto Cliente-Servidor - 1 resposta Como fechar corretamente um Processo Windows Form de um Serviço [C #] - 3 respostas.
Uma pessoa começa como o "Curador" e fica no final de um campo. Todos os outros que jogam estão na extremidade distante (a distância depende da área de jogo selecionada). O .
Atualmente, estou trabalhando em um programa para rastrear minha milha para o meu relatório de despesas mensais para o trabalho. Tudo está funcionando muito bem, no entanto, não posso para a vida de.
Estou tentando entender o SynchronizedMap e corri o código abaixo. Recebo a saída abaixo com uma exceção. Segundo meu entendimento, a exceção é causada quando.
System. Diagnostics. Process não permite "esperar e matar" sem uma corrida # 7343.
Dmitry-Me comentou 30 de março de 2018.
Suponha que eu tenho um System. Diagnostics. Process vinculado a algum processo em execução. Eu quero aguardar até que o processo seja encerrado e se não conseguir sair em cinco segundos, quero que o processo seja encerrado. Aqui está um pseudocódigo:
O problema é que o processo pode sair entre WaitForExit () e Kill () e, em seguida, esse código obtém uma exceção bastante genérica. Não há nenhuma maneira de escrever o código acima, de modo que não exista nenhum potencial para a condição de corrida entre o outro processo que sai e este processo que toma a decisão de encerrar o outro processo ou não.
Mesmo problema na área de trabalho.
Existem três abordagens sobre como isso pode ser resolvido.
O primeiro é que Kill () não faz nada se o processo foi encerrado. Isso violaria o contrato indicado na documentação, mas na verdade é o que é certo. O objetivo de Kill () é "se livrar do processo" e, se acontecer, o processo foi encerrado - tudo bem, nada a ver. Não consigo imaginar um caso razoável em que alguém chamasse cegamente Kill () e depois pegasse a possível exceção e tomasse decisões sobre o que fazer com base em exceção.
O segundo é que um parâmetro com um valor padrão é adicionado a Kill () - de modo que ele se transforma em Kill (bool throwIfExited = true). Isso evita violar o contrato atual, mas honestamente é estúpido.
O terceiro está criando alguma exceção especial exatamente para este caso - de modo que o chamador possa detectar de forma confiável que o processo foi encerrado, inspecionando com programação a exceção. Isso quebraria o contrato e também seria estúpido.
viktor-svub comentou Jul 30, 2018.
Oi! Apenas meu 2c - está jogando uma exceção específica derivada de InvalidOperationException ainda uma violação do contrato? Eu não consideraria isso um, pois qualquer manipulador existente ainda o pegaria e, tecnicamente, é uma instância da mesma classe, não é?
Quanto à outra alternativa - os padrões são incorporados ao chamador, tornando-os parte do contrato e um passivo.
Prefiro recomendar uma alternativa de não-lançamento do TryKill () ou bool KillIfExists do bool.
Dmitry-Me comentou 1 de agosto de 2018.
@ viktor-svub Jogar uma exceção derivada pode se tornar uma violação se o chamador compara o tipo de exceção para a igualdade. Não é tão razoável que seja, talvez haja alguns cenários onde faz sentido. De qualquer forma, quando a sua documentação diz que o código lança SomeException e ele realmente lança SomeDerivedException que formalmente é uma violação do contrato.
viktor-svub comentou 1 de agosto de 2018.
@ Dmitry-Me: certo você é, isso faz sentido. Então, um método alternativo com nome significativo é provavelmente a melhor alternativa restante? Adicionar um argumento ao Kill () seria a quebra de dependência de tempo de execução, pois os padrões são apenas açúcar sintático.
Dmitry-Me comentou 1 de agosto de 2018 e # 8226;
@ viktor-svub Yeap, acho que KillIfExists () ou talvez KillIfNotExited () estaria bem.
Priya91 comentou 7 de dezembro de 2018.
não funciona? A exceção lançada em caso de processo encerrado é InvalidOperationException conforme documentado.
Dmitry-Me comentou 7 de dezembro de 2018.
@ Priya91 É um tipo de trabalho, mas.
Isso não parece uma API clara - você deve esperar que uma corrida se sinta motivada para escrever esse código, uma exceção apresenta sobrecarga sem motivo bom, uma exceção pode desencadear um ponto de interrupção quando executado no debugger por nenhum motivo válido.
Priya91 comentou 7 de dezembro de 2018.
uma exceção apresenta sobrecarga sem razão.
uma exceção pode desencadear um ponto de interrupção quando executado no debugger por nenhum motivo válido.
Esta justificativa aplica-se a todas as exceções que são capturadas e não têm op-op, não significa que não seja útil em outros cenários.
A modificação da API existente não é uma opção por razões compat, e não consigo entender o motivo na introdução de uma nova API. Se você puder encontrar alguns dados sobre o motivo pelo qual o tratamento de exceções é ruim para o seu cenário com alguns números de perf ou outros cenários de uso, então atualize o primeiro comentário da questão com um exemplo de api como aqui.
Dmitry-Me comentou 8 de dezembro de 2018.
@ Priya91 Sim, e na maioria das vezes ter uma exceção que é tratada com um não-op é apenas inútil. Tudo o que você obtém é um ponto de interrupção no depurador, que você não pode fazer de nada útil de qualquer maneira. No entanto, esta parte é menor. A maior parte é que você tem que primeiro estar ciente da raça em potencial e, em seguida, criar esta solução alternativa em vez de usar um método "se livrar desse processo". O display atual da API possui design, não é difícil alterá-lo sem romper a compatibilidade.
Priya91 comentou 9 de dezembro de 2018.
@ Dmitry-Me Se tivermos uma nova API, diga o TryKill Bool (), que retorna verdadeiro se o processo foi morto com um sinal de matar e falso, se não. Como você saberá quando a API retornar falso, a morte não aconteceu devido a algum erro no sistema operacional, ou tentando matar um processo remoto ou se o processo foi encerrado antes de matar? Se você for falso, você não tem certeza se o processo está vivo (no caso dos 2 primeiros motivos) ou não (processo encerrado sozinho). Ou seja, o estado do processo em execução é desconhecido no caso de falso do TryKill, e isso não está adicionando nenhum valor sobre Kill, o que claramente indica se o processo foi morto ou não.
Dmitry-Me comentou 12 de dezembro de 2018.
@ Priya91 Obviamente, o TryKill () não é de muito uso. Deve ser KillIfStillRunning () que pode retornar vazio e apenas mata o processo, não importa se ele saiu ou não e lança uma exceção se não puder matar o processo. Também pode retornar bool para indicar se o processo saiu, mas não vejo muito uso nisso.
Priya91 comentou 12 de dezembro de 2018.
@ Dmitry-Me Eu entendi mal a proposta, você pode atualizar o comentário da questão com um espécime api, você pode usar o exemplo aqui. O speclet tem que definir claramente a finalidade da API através de cenários de uso e o comportamento. Uma vez que temos a proposta, podemos fazer isso através da revisão da API.
jnm2 comentou 27 de dezembro de 2018.
No sidetrail de exceção derivada, não estou convencido de que nunca quebre um contrato para lançar uma exceção mais derivada do que quebra um contrato para retornar um valor mais derivado. Se o contrato for implementado após o LSP, isso nunca importará.
Reflexão, seja envolvendo tipos de instâncias exatas ou membros, é sempre provável quebrar se for usado de maneira incorreta.
&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 . Método WaitForExit ()
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.
Instrui o componente Processo a esperar indefinidamente para que o processo associado saia.
Assembly: System (no System. dll)
A configuração de espera não pôde ser acessada.
Nenhum Id do processo foi configurado e um identificador do qual a propriedade Id pode ser determinada não existe.
Não existe nenhum processo associado a este objeto Processo.
Você está tentando chamar WaitForExit () para um processo que está sendo executado em um computador remoto. Este método está disponível somente para processos que estão sendo executados no computador local.
WaitForExit () faz o thread atual aguardar até o processo associado terminar. Ele deve ser chamado após todos os outros métodos serem chamados no processo. Para evitar o bloqueio do segmento atual, use o evento Exitado.
Esse método instrui o componente Processo a aguardar uma quantidade infinita de tempo para que o processo e os manipuladores de eventos saem. Isso pode fazer com que um aplicativo pare de responder. Por exemplo, se você chamar CloseMainWindow para um processo que tenha uma interface de usuário, a solicitação ao sistema operacional para encerrar o processo associado pode não ser tratada se o processo for gravado para nunca entrar no loop de mensagem.
No Quadro 3.5 e versões anteriores, a sobrecarga WaitForExit () esperava milissegundos MaxValue (aproximadamente 24 dias), não indefinidamente. Além disso, as versões anteriores não esperaram que os manipuladores de eventos saíssem se o tempo MaxValue completo fosse atingido.
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.
Quando um processo associado sai (ou seja, quando é encerrado pelo sistema de operação através de um término normal ou anormal), o sistema armazena informações administrativas sobre o processo e retorna ao componente que chamou WaitForExit (). O componente Processo pode acessar a informação, que inclui o ExitTime, usando o Handle para o processo encerrado.
Como o processo associado saiu, a propriedade Handle do componente já não aponta para um recurso de processo existente. Em vez disso, o identificador pode ser usado apenas para acessar as informações do sistema operacional sobre o recurso do processo. O sistema está ciente de manipulações para processos que não foram lançados pelos componentes do Processo, portanto, mantém as informações ExitTime e Handle na memória até que o componente Processo liberte especificamente os recursos. Por esse motivo, sempre que você ligar para uma instância do Start for Process, chame Close quando o processo associado for encerrado e você não precisa mais de informações administrativas sobre isso. Fechar libera a memória alocada para o processo encerrado.
Consulte a seção Comentários da página de referência da propriedade StandardError.
para uma confiança total para o chamador imediato. Este membro não pode ser usado por código parcialmente confiável.
No comments:
Post a Comment