При использовании Diagnostics.Process блокируется пользовательский интерфейс в WinForms C# 5.0

Мне нужно создать приложение, которое запускает разные команды (PowerShell.exe, ipconfig и т. д.), но когда вызывается ExecuteCommand, пользовательский интерфейс зависает до завершения работы.

Пытался запустить метод с помощью await proc.StandardOutput.ReadToEndAsync(), но не работает. (он висит на указанной строке и не продолжается на следующей строке)

Что я делаю не так?

Заранее спасибо.

ВыполнитьКоманду:

    public static async Task<string> ExecuteCommand(string command)
    {
        try
        {
            System.Diagnostics.Process proc = new System.Diagnostics.Process();
            System.Diagnostics.ProcessStartInfo procStartInfo = new System.Diagnostics.ProcessStartInfo("cmd", "/c " + command);
            procStartInfo.RedirectStandardOutput = true;
            procStartInfo.RedirectStandardInput = true;
            procStartInfo.UseShellExecute = false;
            procStartInfo.CreateNoWindow = true;

            proc.StartInfo = procStartInfo;
            proc.Start();

            proc.WaitForExit();
            var message = proc.StandardOutput.ReadToEndAsync();

            //var error =  await proc.StandardError.ReadToEndAsync();

            proc.Close();

            //var errorContent = error;
            return message.Result;
        }
        catch (Exception objException)
        {
            return objException.Message;
        }
    }

Регистратор:

public void Logger(string value)
{
    logtxt.AppendText("[" + DateTime.Now + "]: " + value + Environment.NewLine);
    logtxt.SelectionStart = logtxt.Text.Length;
    logtxt.ScrollToCaret();
}

Активен:

private async Task<bool> IsActive()
{
    string text = await ExecuteCommand("PowerShell.exe -Command \"Get-VPNconnection -AllUserConnection\"");

    Logger(text);

    ...more code...
}

Form1_Shown (я переместил приведенный ниже код из Form_Load, потому что до появления пользовательского интерфейса требуется время):

private void Form1_Shown(object sender, EventArgs e)
{
    if (IsActive().Result)
    {
      ...more code...
    }
}

жду [Process].WaitForExitAsync()

Jimi 04.07.2024 23:28

также отсутствует await на ReadToEndAsync

Santiago Squarzon 04.07.2024 23:29

Это распространенная проблема с winforms, если вы не разрешите запуск процесса в фоновом режиме. Не уверен, но у Джими может быть ответ.

jdweng 04.07.2024 23:30

Ни PowerShell.exe, ни ipconfig.exe не требуют какого-либо участия "cmd", поэтому я не понимаю, почему вы сначала используете cmd /c, или, точнее, Environment.SystemDirectory с \cmd.exe /S /D /C "command"

Compo 05.07.2024 01:14
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
4
64
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Вот ваша проблема:

private void Form1_Shown(object sender, EventArgs e)
{
    if (IsActive().Result)
    {
      ...more code...
    }
}

Чтение свойства Результат является блокирующей операцией. Это не только блокирует поток пользовательского интерфейса, но, что еще хуже, вызывает взаимоблокировку, поскольку в асинхронном потоке есть await, которые захватывают контекст пользовательского интерфейса, поскольку они не настроены с помощью .ConfiguredAwait(false). Правильный способ решить эту проблему — использовать полную асинхронность:

private async void Form1_Shown(object sender, EventArgs e)
{
    if (await IsActive())
    {
      ...more code...
    }
}

Вы можете узнать больше об этой распространенной проблеме, прочитав знаменитую статью Стивена Клири Не блокируйте асинхронный код.

все работает так, как я хотел, спасибо

Hello World 07.07.2024 11:56

Другие вопросы по теме