取消正在运行的进程

8
我运行一个进程,在命令行中执行一个带参数的exe文件,这个过程需要时间才能完成。同时,我会展示一个对话框,其中包含进度条和取消按钮。当用户点击取消按钮时,进程应该停止/中止。我有两种方法可以实现这个功能:
A. 在主窗体中声明一个公共静态Process类对象,并在进度对话框中点击取消按钮时中止它:
public partial class frmMain : Form
{
    public static Process Process = new Process();

    public static bool ExecuteCommand(string sCommandLineFile, string sArguments)
    {
        Process.StartInfo.FileName = sCommandLineFile;
        Process.StartInfo.Arguments = sArguments;
        Process.StartInfo.CreateNoWindow = true;
        Process.StartInfo.UseShellExecute = false;
        Process.StartInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;

        Process.Start();
        Process.WaitForExit();
    }
}

如何从进度窗口中关闭/放弃进程:

public partial class frmProgress : Form
{
    private void btnCancel_Click(object sender, EventArgs e)
    {
        frmMain.Process.Close();
        frmMain.Process.Dispose();
    }
}

B. 或者不要调用Process.WaitForExit();,而是使用Process.HasExited检查进程是否正在运行,并在单击取消按钮时取消它:

public static bool IsCancelled = false;

Process.StartInfo.FileName = sCommandLineFile;
Process.StartInfo.Arguments = sArguments;
Process.StartInfo.CreateNoWindow = true;
Process.StartInfo.UseShellExecute = false;
Process.StartInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;

while (!Process.HasExited)
{
    Thread.Sleep(100);
    Application.DoEvents();

    if (IsCancelled)
    {
        Process.Close();
        Process.Dispose();
    }
}

public partial class frmProgress : Form
{
    private void btnCancel_Click(object sender, EventArgs e)
    {
        frmMain.IsCancelled = true;
    }
}

怎样才是正确的做法?

1个回答

8
一个混合体。
public partial class frmMain : Form
{
    public static Process Process = new Process();

    public static bool ExecuteCommand(string sCommandLineFile, string sArguments)
    {
        Process.StartInfo.FileName = sCommandLineFile;
        Process.StartInfo.Arguments = sArguments;
        Process.StartInfo.CreateNoWindow = true;
        Process.StartInfo.UseShellExecute = false;
        Process.StartInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;

        Process.Start();
        // Process.WaitForExit(); // Don't wait here, you want the application to be responsive
    }
}

在取消处理程序中

private void btnCancel_Click(object sender, EventArgs e)
{
    frmMain.Process.Close(); // or .Kill()
    frmMain.Process.Dispose();
}

当然,现在您需要一种方法来查找进程是否以正常方式退出。定期使用Process.HasExited进行轮询以获取终止情况。最好使用计时器来完成此操作。我目前不确定,但可能会有一个事件可以处理这个问题。
第二种解决方案存在问题,即在仍然阻塞用户界面的同时积极等待进程完成。而且它正在使用Application.DoEvents(),您应该尽量避免使用它,因为它会创建各种不良副作用(例如,在递归中您将能够多次运行相同的代码)。

1
不需要轮询 Process.HasExited,只需执行 frmMain.Process.CanRaiseEvents = true,然后订阅 Exited 事件即可。 - Scott Chamberlain
你的意思是 frmMain.Process.EnableRaisingEvents = true(而不是 CanRaiseEvents)吗? - AhmadYo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接