使用外部进程冻结 UI

Mr.*_*ice 2 .net c# winforms

我已经实现了以下代码(改编自教程),以便运行命令提示符窗口、运行程序并读取输出。该代码是从嵌套在用户控件中的 ButtonClick 事件处理程序调用的。

我的印象是,这将允许我的程序的其余部分在外部进程运行时运行,因为这些方法是“异步”的。然而,情况似乎并非如此,因为我的 UI 在操作运行时会冻结。我应该补充一点,cmd 进程结束时收到的输出是正确的。

很抱歉转储这样的代码,只是不知道此时还能做什么!

任何帮助将不胜感激。

public static void runExternalProcess()
{
    StringBuilder output = new StringBuilder();

    Process cmd = new Process();
    cmd.StartInfo.FileName = "cmd.exe";          
    cmd.StartInfo.UseShellExecute = false;
    cmd.StartInfo.CreateNoWindow = true;
    cmd.StartInfo.RedirectStandardOutput = true;

    cmd.OutputDataReceived += new DataReceivedEventHandler(outputEventHandler);        
    cmd.StartInfo.RedirectStandardInput = true;        
    cmd.Start();
    cmd.BeginOutputReadLine();      

    StreamWriter sortStreamWriter = cmd.StandardInput; 
    StreamWriter sw = cmd.StandardInput;

    if (sw.BaseStream.CanWrite)
    {
        sw.WriteLine("ping www.google.com");
    }

    sw.Close();

    cmd.WaitForExit();

    MessageBox.Show(output.ToString());

    cmd.Close();
}

private static void outputEventHandler(object sendingProcess, DataReceivedEventArgs e)
{
    if (!String.IsNullOrEmpty(e.Data))
    {
        output.Append(e.Data + Environment.NewLine);
    }
}
Run Code Online (Sandbox Code Playgroud)

Mat*_*and 5

你的问题在这里:

cmd.WaitForExit();
Run Code Online (Sandbox Code Playgroud)

这是一个阻塞调用。

如果您想在不阻塞的情况下响应进程退出,则需要为 Exited 事件添加处理程序。


SwD*_*n81 5

Exited注册参加该活动并在那里展示怎么样MessageBox

StringBuilder output = new StringBuilder();
Process cmd = new Process();

public void RunExternalPing()
{
   cmd.StartInfo.FileName = "cmd.exe";
   cmd.StartInfo.UseShellExecute = false;
   cmd.StartInfo.CreateNoWindow = true;
   cmd.StartInfo.RedirectStandardOutput = true;
   cmd.StartInfo.RedirectStandardInput = true;

   cmd.EnableRaisingEvents = true;
   cmd.OutputDataReceived += 
      new DataReceivedEventHandler(cmd_OutputDataReceived);
   cmd.Exited += new EventHandler(cmd_Exited);

   cmd.Start();
   cmd.BeginOutputReadLine();
   StreamWriter sw = cmd.StandardInput;
   sw.WriteLine("ping www.google.com");
   sw.Close();
}

void cmd_Exited(object sender, EventArgs e)
{
   MessageBox.Show(output.ToString());
   cmd.Dispose();
}

private void cmd_OutputDataReceived(object sender, DataReceivedEventArgs e)
{
   if (!String.IsNullOrEmpty(e.Data))
   {
      output.Append(e.Data + Environment.NewLine);
   }
}
Run Code Online (Sandbox Code Playgroud)

来自 MSDN:

当关联进程退出时,有两种方式收到通知:同步和异步。同步通知依赖于调用 WaitForExit 方法来暂停应用程序的处理,直到关联的组件退出。异步通知依赖于 Exited 事件。无论哪种情况,EnableRaisingEvents 都必须设置为 true,以便 Process 组件接收进程已退出的通知。