So I noticed that there's a method called WaitForExit that accepts and int as argument (milliseconds) so if the process isn't able to exit itself, I just killed it after some seconds.
Something like this.
if (!CMD.WaitForExit(3000))
CMD.Kill();
The thing is that meanwhile I'd like to save the output, so I noticed that there's an async method WaitForExitAsync but this one doesn't accept these milliseconds.
// Wait for exit async...
// Meanwhile save the output till it kills itself.
while (CMD.StandardOutput.ReadLine() != null)
standard_output = StandardOutput.ReadLine();
Any idea how to do this? Thanks!
You need to use CancellationTokenSource. It has a ctor which accepts a TimeSpan
var timeoutSignal = new CancellationTokenSource(TimeSpan.FromSeconds(3));
try
{
await CMD.WaitForExitAsync(timeoutSignal.Token);
} catch (OperationCanceledException)
{
CMD.Kill();
}
When the CTS signals then the awaited operation will throw an OperationCanceledException. So you need to wrap your await call into a try-catch to handle cancelled operation properly.
UPDATE #1: Capture STDOUT with async wait of exit
First let me share with you the naive version of the code
Console.WriteLine("Launch ping with fifteen retries");
var terminal = Process.Start(new ProcessStartInfo("/sbin/ping")
{
RedirectStandardOutput = true,
Arguments = "-c 15 stackoverflow.com",
UseShellExecute = false,
});
_ = Task.Run(() =>
{
string line = null;
while ((line = terminal.StandardOutput.ReadLine()) != null)
Console.WriteLine(line);
});
var timeoutSignal = new CancellationTokenSource(TimeSpan.FromSeconds(3));
try
{
await terminal.WaitForExitAsync(timeoutSignal.Token);
Console.WriteLine("Ping has been Finished");
}
catch (OperationCanceledException)
{
terminal.Kill();
Console.WriteLine("Ping has been Terminated");
}
ping.exe rather than I can run /sbin/ping commandStandardOutput reading to a separate thread (Task.Run)
The Process class does expose a capability to read data asynchronously from the StandardOutput without the need to do extra tricks
Console.WriteLine("Launch ping with fifteen retries");
var terminal = new Process()
{
StartInfo = new ProcessStartInfo("/sbin/ping")
{
RedirectStandardOutput = true,
Arguments = "-c 15 stackoverflow.com",
UseShellExecute = false,
}
};
terminal.OutputDataReceived += (s, e) => Console.WriteLine(e.Data);
terminal.Start();
terminal.BeginOutputReadLine();
var timeoutSignal = new CancellationTokenSource(TimeSpan.FromSeconds(3));
try
{
await terminal.WaitForExitAsync(timeoutSignal.Token);
Console.WriteLine("Ping has been Finished");
}
catch (OperationCanceledException)
{
terminal.Kill();
Console.WriteLine("Ping has been Terminated");
}
Let me highlight only the differences
StartInfo propertyOutputDataReceived event
Data property contains the newly available informationStart methodBeginOutputReadLine method to tell the Process fire the above event handler whenever new data is available on the standard outputThe new .NET 6 comes with WaitAsync method that allows asynchronously waiting for a task with a timeout.
await process.WaitForExitAsync().WaitAsync(TimeSpan.FromMilliseconds(1000));
if (!process.HasExited)
{
//timeout!
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With