Если вы закрываете процесс, вызывая .CloseMainWindow()
, , заверните вызов в блок try / catch - это то, что нужно сделать.
Сделайте это:
try
{
process.CloseMainWindow()
}
catch (InvalidOperationException)
{
// purposely do nothing here - the process exited before we told it to.
}
Это потому, что проверка свойств процесса перед его остановкой создает условие гонки : и проверка свойства, и вызов .CloseMainWindow()
мчатся, чтобы выяснить, какое из них может быть завершено первый.
Рассмотрим эту серию событий:
- Процесс запущен
- Ваш код звонит
process.HasExited
и получает false
- Процесс завершается сам по себе, поскольку он завершен
- Поскольку шаг 2 вернул
false
, ваш код вызывает process.CloseMainWindow()
и получает InvalidOperationException: Process has exited, so the requested information is not available.
Никакое ускорение вашего кода, ни использование блокировок, ни какая-либо другая стратегия не могут гарантировать, что процесс не завершится после вашего оператора if
. Всегда есть условия гонки. Поэтому вместо этого используйте try/catch
.
Если вам необходимо отслеживать, был ли процесс когда-либо запущен, вы можете заключить процесс в свой собственный класс. Вы можете использовать блокировку при запуске процесса и установить логический флаг, чтобы указать, что он был запущен.
class ProcessWrapper
{
public HasStarted;
public ProcessWrapper(Process p, ProcessStartInfo psi)
{
// do argument and filename validation etc. here
lock(HasStarted)
{
p.Start(psi);
HasStarted = true;
}
}
}