Уничтожение процесса при выходе - PullRequest
1 голос
/ 21 марта 2009

В моем проекте есть объект, который создает процесс. Функция Dispose этого объекта убивает процесс (или пытается). Однако, если программа падает, она оставляет процесс запущенным и не очищается. Что приводит к сбою программы в следующий раз, потому что он пытается запустить процесс снова и не может получить блокировку для него.

Как я могу убедиться, что этот процесс убит? Я всегда использую объект, который создает процесс в using блоке

Для справки я использую C # и .NET 3.5

Ответы [ 6 ]

3 голосов
/ 22 марта 2009

определение «вылетов»; Существуют разные уровни сбоя ... например, если что-то активно убивает ваш процесс, у вас будет очень мало шансов запустить любые Dispose / finalizer и т. д. - но если ваш поток разматывается изящно (даже через исключение), вы должны быть в порядке ( так как вы используете using). Можете ли вы уточнить, что это за настройка?

1 голос
/ 22 марта 2009

Если вы хотите обеспечить завершение дочернего процесса, рассмотрите возможность создания отдельного и более простого сторожевого процесса, отслеживая пространство процесса для завершения любого из них. Обычно это легче сделать пуленепробиваемым. Невозможно гарантировать выполнение кода очистки при всех обстоятельствах.

Тем не менее, вы на самом деле не предоставляете достаточно контекста о том, как создается ваш дочерний процесс, чтобы дать какой-либо соответствующий совет о том, как сконструировать сторожевой таймер, чтобы знать о родительском и дочернем процессах.

1 голос
/ 22 марта 2009

Я знаю, что это заставит меня кричать, но как насчет Enviroment.Exit (). Это должно убивать все, каждый раз =) Тем не менее, все же лучше использовать вышеуказанные опции.

Также:

В вашем Program.cs перед вызовом Application.Run (Форма) сделайте следующее:

AppDomain.CurrentDomain.UnhandledException + = новый UnhandledExceptionEventHandler (CurrentDomain_UnhandledException);

, а затем вставьте обработчик, похожий на этот:

    static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
    {
        try
        {
            String CurrentThreadName = System.Threading.Thread.CurrentThread.Name;

            if (e.IsTerminating)
                Logger.Log("Program", 0, String.Format("Received fatal unhandled exception on '{0}' thread.  Exception will follow.", CurrentThreadName), MsgCategory.Critical, 50);
            else
                Logger.Log("Program", 0, String.Format("Received unhandled exception on '{0}' thread.  Exception will follow.", CurrentThreadName), MsgCategory.Error, 25);

            if (e.ExceptionObject != null)
                Logger.LogException("Program", String.Format("Unhandled System Exception on '{0}' thread.", CurrentThreadName), 50, (Exception)e.ExceptionObject);
        }
        catch
        {
        }
        if (e.IsTerminating)
        {
            Exception ThisException = (Exception)e.ExceptionObject;
            String CurrentThreadName = System.Threading.Thread.CurrentThread.Name;
            MessageBox.Show(
                    String.Format(Localization.GetString("fatal_error"), ThisException.GetType().ToString(), ThisException.Message, ThisException.StackTrace, CurrentThreadName)
                    , Localization.GetString("dialogtitle")
                    , MessageBoxButtons.OK
                    , MessageBoxIcon.Error
                    , MessageBoxDefaultButton.Button1);
        }
    }
0 голосов
/ 22 марта 2009

Что вам действительно нужно, так это двусторонний мониторинг процессов, чтобы в случае смерти родительского или дочернего процесса вы могли предпринять соответствующие действия. Самый простой способ сделать это - заставить их пинговать друг друга по таймеру (каждые 30 секунд, например, вам нужно настраиваться на ваши нужды), и если к моменту отправки следующего пинга ответа не будет, вы можете принять другой процесс умер, заблокирован или иным образом перестал играть приятно.

Если родитель перестает отвечать, ребенок должен просто выйти. Если ребенок перестает отвечать, убейте его и начните новый.

Как реализовать пинг, оставлено для читателя как упражнение, но подойдет любой механизм IPC - оконные сообщения, вызовы RPC, каналы ... все, что поражает ваше воображение. Будь проще; Я уверен, что в .net есть что-то, что вы можете использовать.

0 голосов
/ 22 марта 2009
Foo bar = new Foo();
try
{
  bar.DoSomething();
}
catch // if required
{
}
finally
{
  if(bar != null)
  {
    bar.Dispose(); // code from finally clause is ~always executed
  }
}

, что равно

using(Foo bar = new Foo())
{
  // ..
}
0 голосов
/ 21 марта 2009

Какая программа запускается? Должна быть возможность запустить второй экземпляр, даже если первый экземпляр все еще работает - запуск процесса ничего не блокирует (если только сама программа не делает что-то странное).

А как объект запускает процесс? Если у него есть дескриптор, он должен иметь возможность немедленно завершить его, вызвав TerminateProcess API.

Вот действительно хакерское решение проблемы обеспечения того, что порожденный процесс умрет, если умирает вызывающий: вызов DebugActiveProcess , передав идентификатор дочернего процесса.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...