3

我正在使用 Visual C# 2005 (net framework 2) 创建一个 GUI 应用程序。我使用以下代码启动一个进程:

Process process = new Process();
process.StartInfo = new ProcessStartInfo("app.exe");
process.StartInfo.WorkingDirectory = "";
process.StartInfo.Arguments = "some arguments";
process.Start();
process.WaitForExit();

我希望我的应用程序等到这个过程完成,所以我使用了 WaitForExit。但是当 app.exe 运行时 GUI 窗口会冻结。我希望它响应(例如按下取消按钮),但我不希望代码继续,因为之后还有另一个进程要启动。提前致谢!

4

6 回答 6

5

您可以捕获Process 类的Exited事件:

void someMethod()
{
    //...possibly more code here
    Process process = new Process();
    process.StartInfo = new ProcessStartInfo("app.exe");
    process.StartInfo.WorkingDirectory = "";
    process.StartInfo.Arguments = "some arguments";
    process.Exited += new EventHandler(ProcessExited);
    process.Start();
}

void ProcessExited(object sender, System.EventArgs e)
{
  //Handle process exit here
}
于 2009-11-13T09:21:31.670 回答
4

您在应用程序的唯一线程上等待进程,该线程也负责处理所有 GUI 事件。如果您想等待某个事件(如某个其他进程完成)并且仍然让您的代码通知该事件,那么您必须等待另一个线程或使用事件处理程序。

于 2009-11-13T09:25:55.390 回答
3

这应该会有所帮助。基本上对于像这样的 Windows 窗体和简单任务,BackgroundWorker 很方便。下面是一些简单的代码来启动记事本并等待它关闭,或者用户可以通过单击取消来终止它。

    public Form1()
    {
        InitializeComponent();
        backgroundWorker1.WorkerSupportsCancellation = true;
    }

    private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
    {
        Process process = new Process();
        process.StartInfo = new ProcessStartInfo("notepad.exe");
        process.Start();
        while (!process.HasExited)
        {
            if (backgroundWorker1.CancellationPending)
            {
                process.Kill();
                continue;
            }
            else
                Thread.Sleep(1000);
        }
    }

    private void Start_Click(object sender, EventArgs e)
    {
        backgroundWorker1.RunWorkerAsync();
    }

    private void Cancel_Click(object sender, EventArgs e)
    {
        backgroundWorker1.CancelAsync();
    }
于 2009-11-13T09:38:56.477 回答
2

为了接收 Exited 事件的回调,EnableRaisingEvents 必须设置为 true。

Process correctionProcess = Process.Start(startInfo);
correctionProcess.EnableRaisingEvents = true;
correctionProcess.Exited += new EventHandler(ProcessExited); 

使用 exited 对我来说效果很好,并且给了我很大的灵活性,可以按顺序、部分并发或一次全部运行 - 无需锁定 UI。

于 2013-05-24T17:23:23.873 回答
1

也许您应该使用BackgroundWorker实施解决方案。它很容易实现并且可以做你想做的事。

您需要做的是在表单中添加一个 BackgroundWorker 的实例,然后从 BackgrondWorker RunWorkerAsync 方法调用运行 App.exe 的进程。然后,您可以监视 CancelationPending 属性以停止进程或 RunWorkerCompleted 事件以在进程退出后执行任何必要的操作。

还有另一个关于 BackgroundWorker 取消的问题

于 2009-11-13T09:22:27.103 回答
0

解决方案是使用多线程,首先添加:

使用 System.Threading;

然后看下面的代码:

    Process process = new Process();
    process.StartInfo = new ProcessStartInfo("app.exe");
    process.StartInfo.WorkingDirectory = "";
    process.StartInfo.Arguments = "some arguments";

//启动一个启动进程的新线程,因此当您调用 WaitForExit 时它不会冻结主线程

    Thread th= new Thread(() =>
    {
        process.Start();
        process.WaitForExit();
    });
    th.Start();

如果你想背靠背运行多个进程,这是另一种情况,你需要使用类似进程列表的东西,看看下面的代码

    List<Process> processes = new List<Process>();;

    Process process = new Process();
    process.StartInfo = new ProcessStartInfo("app.exe");
    process.StartInfo.WorkingDirectory = "";
    process.StartInfo.Arguments = "some arguments";

    processes.Add(process); 

// 我手动添加另一个,但您可以使用循环为例

    Process process2 = new Process();
    process.StartInfo = new ProcessStartInfo("app.exe");
    process.StartInfo.WorkingDirectory = "";
    process.StartInfo.Arguments = "some arguments";

    processes.Add(process2);

// 然后你将通过你的线程启动它们,第二个进程将等到第一个完成而不阻塞 UI

    Thread th= new Thread(() =>
    {
            for (int i = 0; i < processes.Count; i++)
            {
                    processes[i].Start();
                    processes[i].WaitForExit();
             }
    });
    th.Start();
于 2013-07-05T17:07:07.003 回答