Como o título sugere, existe um equivalente Process.Start
(permite executar outro aplicativo ou arquivo em lotes) que eu possa aguardar?
Estou jogando com um pequeno aplicativo de console e este parecia o lugar perfeito para usar assíncrono e aguardar, mas não consigo encontrar nenhuma documentação para esse cenário.
O que estou pensando é algo nesse sentido:
void async RunCommand()
{
var result = await Process.RunAsync("command to run");
}
c#
async-await
c#-5.0
linkerro
fonte
fonte
Process.Start
é assíncrono e o OP parece querer uma versão síncrona.Respostas:
Process.Start()
apenas inicia o processo, não espera até terminar, portanto, não faz muito sentido fazê-loasync
. Se você ainda deseja fazer isso, pode fazer algo assimawait Task.Run(() => Process.Start(fileName))
.Mas, se você quiser aguardar assincronamente o processo terminar, poderá usar o
Exited
evento junto comTaskCompletionSource
:fonte
process
eprocess.StartInfo
altera o que acontece quando você as executa.Start()
. Se você, por exemplo, telefonar.EnableRaisingEvents = true
antes de definir asStartInfo
propriedades conforme visto aqui, as coisas funcionarão conforme o esperado. Se você configurá-lo mais tarde, por exemplo, para mantê-lo junto.Exited
, mesmo que você o tenha chamado antes.Start()
, ele não funciona corretamente - é.Exited
acionado imediatamente, em vez de esperar que o Processo realmente saia. Não sei por que, apenas uma palavra de cautela.process.SynchronizingObject
deve ser definido como componente de formulários para evitar que métodos que manipulam eventos (como Exited, OutputDataReceived, ErrorDataReceived) sejam chamados em threads separados.Process.Start
emTask.Run
. Um caminho UNC, por exemplo, será resolvido de forma síncrona. Esse snippet pode levar até 30 segundos para ser concluído:Process.Start(@"\\live.sysinternals.com\whatever")
Aqui está a minha opinião, com base na resposta de svick . Ele adiciona redirecionamento de saída, retenção de código de saída e tratamento de erros um pouco melhor (descartando o
Process
objeto mesmo que não possa ser iniciado):fonte
async Task<int> RunProcessAsync(string fileName, string args)
. Eu adaptei este exemplo e passo três objetos um por um. Como posso esperar para levantar eventos? por exemplo. diante dos meus Stopps aplicação .. muito obrigadoDispose
anule o manipulador de eventos; portanto, teoricamente, se você ligasse,Dispose
mas mantivesse a referência, acredito que seria um vazamento. No entanto, quando não há mais referências aoProcess
objeto e ele é coletado (lixo), não há ninguém que aponte para a lista de manipuladores de eventos. Portanto, ele é coletado e agora não há referências aos delegados que estavam na lista; portanto, eles são coletados como lixo.Dispose
limpa alguns recursos, mas não impede que uma referência vazada permaneça porprocess
perto. De fato, você notará queprocess
se refere aos manipuladores, mas oExited
manipulador também tem uma referência aprocess
. Em alguns sistemas, essa referência circular impediria a coleta de lixo, mas o algoritmo usado no .NET ainda permitiria que tudo fosse limpo, desde que tudo viva em uma "ilha" sem referências externas.Aqui está outra abordagem. Conceito semelhante às respostas de svick e Ohad, mas usando um método de extensão no
Process
tipo.Método de extensão:
Exemplo de caso de uso em um método que contém:
fonte
Eu criei uma classe para iniciar um processo e ele estava crescendo nos últimos anos devido a vários requisitos. Durante o uso, descobri vários problemas com a classe Process ao descartar e até ler o ExitCode. Então, tudo isso foi corrigido pela minha turma.
A classe tem várias possibilidades, por exemplo, ler saída, iniciar como administrador ou usuário diferente, capturar exceções e também iniciar tudo isso incl. Cancelamento. Bom é que a saída de leitura também é possível durante a execução.
fonte
Eu acho que tudo que você deve usar é o seguinte:
Exemplo de uso:
fonte
CancellationToken
, se cancelá-lo não éKill
o processo?CancellationToken
noWaitForExitAsync
método é necessário simplesmente para poder cancelar uma espera ou definir um tempo limite. A matança de um processo pode ser feita emStartProcessAsync
: `` `tente {aguarde processo.WaitForExitAsync (cancellationToken); } catch (OperationCanceledException) {process.Kill (); } `` `CancellationToken
, o cancelamento do token deve resultar no cancelamento da operação, não no cancelamento da espera. Isso é o que o chamador do método normalmente esperaria. Se o chamador deseja cancelar apenas a espera e deixar a operação ainda em execução em segundo plano, é bastante fácil fazer isso externamente ( aqui está um método de extensãoAsCancelable
que está fazendo exatamente isso).Estou realmente preocupado com a eliminação do processo, que tal esperar pela saída assíncrona ?, esta é a minha proposta (com base no anterior):
Em seguida, use-o assim:
fonte