Завершение процесса C # изящно не работает

У меня есть приложение, которое порождает несколько потоков, один из которых запускает iPerf исполняемый файл, который используется для мониторинга надежности сети. Этот процесс будет выполняться бесконечно, пока пользователь не попытается закрыть окно. Вот где возникает проблема. Я пытаюсь корректно завершить этот процесс, чтобы сервер iPerf не зависал, но я не могу заставить это работать. Я могу выключить его просто так, если я запустил команду вручную из командной строки и нажал Ctrl+c, но это, похоже, нелегко сделать программно.

Я пробовал несколько вещей, в том числе process.Kill();, process.StandardInput.Close() или даже process.StandardInput.WriteLine("\x3");, но ни один из них, похоже, не отправляет процессу постепенное завершение работы. process.Kill(); приводит к зависанию сервера или невозможности его запуска в следующий раз, а две другие опции вообще не останавливают сервер. Но мануал ctrl+c работает нормально.

Вот фрагмент моего кода:

iperf_proc = new Process();
iperf_proc.StartInfo.FileName = Application.StartupPath + ".\\iperf3.exe";
String argumentStr = " -c " + test_data.host + " -t 0";
iperf_proc.StartInfo.Arguments = argumentStr;
iperf_proc.StartInfo.UseShellExecute = false;
iperf_proc.StartInfo.RedirectStandardOutput = true;
iperf_proc.StartInfo.RedirectStandardInput = true;
iperf_proc.StartInfo.RedirectStandardError = true;
iperf_proc.Start();
iperfRunning = true;
iperf_proc.BeginOutputReadLine();
iperf_proc.BeginErrorReadLine();
while (false == iperf_proc.HasExited)
{
    if (true == processCancelled)
    {
        iperf_proc.StandardInput.Close(); // Doesn't Work!
        iperf_proc.StandardInput.WriteLine("\x3"); // Doesn't Work!
        iperf_proc.StandardInput.Flush(); // Doesn't Work!
    }
}
iperf_proc.WaitForExit();

Любая помощь приветствуется. Спасибо!

ОБНОВЛЕНИЕ:

Основываясь на предложении Ханса в комментарии, я попытался добавить что-то в код, чтобы отправить событие ctrl+c.

[DllImport("kernel32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool GenerateConsoleCtrlEvent(uint dwCtrlEvent, uint dwProcessGroupId);
private enum CtrlEvents
{
     CTRL_C_EVENT = 0,
     CTRL_BREAK_EVENT = 1
}
private void closeBtn_Click(object sender, EventArgs e)
{
     processCancelled = true;
     //iperf_proc.CloseMainWindow();
     bool succeeded = GenerateConsoleCtrlEvent((uint)CtrlEvents.CTRL_C_EVENT, (uint)iperf_proc.Id);
}

Это вообще не сработало. Процесс все еще запущен, и добавленная функция возвращает false. Я проверил, что переданный идентификатор процесса соответствует идентификатору процесса в диспетчере задач. Все в порядке, но функция GenerateConsoleCtrlEvent возвращает false. Есть идеи, почему это может быть?


person MZimmerman6    schedule 18.02.2016    source источник
comment
pinvoke.net/default.aspx/kernel32/GenerateConsoleCtrlEvent.html   -  person Hans Passant    schedule 18.02.2016
comment
@HansPassant Спасибо за ссылку. Возможно, я неправильно понимаю ссылку или неправильно реализовал код, но я соответствующим образом обновил свой вопрос выше, чтобы показать код, который я добавил для этого события консоли, и, похоже, он на самом деле ничего не делает.   -  person MZimmerman6    schedule 19.02.2016
comment
Также обратите внимание, что мне нужно иметь доступ к выходным данным этого процесса как можно ближе к реальному времени.   -  person MZimmerman6    schedule 19.02.2016


Ответы (1)


BeginOutputReadLine

Ссылка описывает, как сделать именно то, что вы ищете в примере.

Почему бы не использовать встроенное событие Exited для ожидания, чтобы не блокировать? Особенно, если вы создаете несколько потоков. Если вы хотите заблокировать, также доступен WaitForExit ().

if (true == processCancelled)
{
    iperf_proc.StandardInput.Close(); // Doesn't Work!
    iperf_proc.StandardInput.WriteLine("\x3"); // Doesn't Work!
    iperf_proc.StandardInput.Flush(); // Doesn't Work!
}

Если закрыть стандартный ввод, как вы собираетесь его писать / сбрасывать?

После того, как у вас есть WaitForExit (), вам также нужно закрыть ()

person Christopher Lawrence    schedule 18.02.2016
comment
Я должен был прояснить, что строки здесь не обязательно в таком порядке, или даже все в коде сразу. Просто показываю то, что пробовал. - person MZimmerman6; 18.02.2016
comment
Я также не совсем уверен, что вы понимаете то, о чем я спрашиваю. Мне нужно изящно завершить процесс, к которому у меня есть дескриптор. Если этот процесс не завершается корректно, сервер зависает. - person MZimmerman6; 19.02.2016