Чистое уничтожение консольного приложения из группы консольных приложений - PullRequest
6 голосов
/ 08 ноября 2011

У меня есть форма Windows, которая создает несколько консольных приложений одной и той же программы (она вызывает program.exe любое количество раз), используя

process.start().  

Я ищу способ определить конкретный запускприложение и убейте его полностью (т.е. аккуратно закройте 5-й процесс program.exe, но оставьте все остальные процессы запущенными).Я могу идентифицировать каждый отдельный процесс program.exe с помощью идентификаторов, которые были даны при запуске процессов, но я не могу закрыть приложение, кроме как вызвать

process.kill() 

, который не выполняетуберите закрытие приложения.

Я считаю, что я не могу использовать

process.CloseMainWindow()

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

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

Я определяю каждый новый процесс следующим образом:

Process process = new Process();
process.StartInfo = info;

ExecutionDetails details = new ExecutionDetails(run_id, process, info, session_type, strategy_type, name, ExecutionViewModel);

lock (_runs)
_runs.Add(run_id, details); // will throw on Add if duplicate id, prevent duplicate
ExecutionViewModel.NewRun(details); // add to the view model

process.Start();

Где run_id - это GUID, который идентифицирует каждый процесс.

В отдельном классе у меня есть код, который выполняется через процесс, на который ссылается только через командную строку, которая запускает программу (то есть вызывает программу, предоставляет переменные конфигурации и т. Д.).

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

** РЕДАКТИРОВАТЬ - мой код для обработки событий, который я пытался реализовать, но он не работает.

Код в главном окне

 public void KillOne() {
     foreach (var details in _runs.Values) {
         if(details.IsSelected) {
             StrategyStateManager.SessionClosed(this, details.RunId);
                } } }

Код в StrategyStateManager (средний класс, используемый для хранения переменных и событий, используемых в программе)

public delegate void StrategyCloseEventHandler(object sender, StrategyCloseEventArgs e);

    public static void SessionClosed(object sender, Guid id)
    {
        if(CloseSession != null)
            CloseSession(sender, new StrategyCloseEventArgs(id));
    }


public class StrategyCloseEventArgs : EventArgs
{

    private readonly Guid id;

    public StrategyCloseEventArgs(Guid run_id)
    {
        id = run_id;
    }

    public Guid GetRunID()
    {
        return id;
    }

}

Код в процессе, которыйзапускается главным окном

 StrategyStateManager.CloseSession += (closeStrategy);

 void closeStrategy(object sender, StrategyCloseEventArgs e)
    {
        if (e.GetRunID() == run_id)
        {
            strategy.cleanupForShutdown();
            DBSaverSimple.shutdownAll();
            logger.Warn("Simulation run stopped by user");
        }
    }

Ответы [ 2 ]

5 голосов
/ 08 ноября 2011

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

Это предполагает, конечно, что у вас естьсоздал способ для чистого отключения программы.

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

Другая возможность состоит в том, чтобысоздайте имя EventWaitHandle для каждого запускаемого процесса, передав имя этого события консольному приложению в командной строке.Тогда консольная программа может иметь поток, который выполняет WaitOne для этого события.Когда событие установлено, программа инициирует чистое отключение.Это более надежно, чем широковещательная датаграмма.Конечно, он использует другой дескриптор для каждого процесса, но это не будет проблемой, если у вас нет тысяч процессов.

См. Отправка сообщения из одного запущенного консольного приложения в другое для примераиспользование именованного дескриптора ожидания для связи между процессами.

2 голосов
/ 08 ноября 2011

Звучит так, как будто вы будете иметь определенное состояние в вашем отдельном коде, выполняемом подпроцессами, и в этот момент вы хотите, чтобы этот процесс завершился.Почему бы вам не вызвать Process.GetCurrentProcess().Kill(); или даже Process.GetCurrentProcess().Close(); в конце этого пути к коду?

Таким образом, когда он завершит выполнение, он закроет / уничтожит себя, а остальные процессы продолжат работать какони считают нужным (пока они тоже не достигнут своей конечной точки)?

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