C# 在进程运行时取消进程

C# 在进程运行时取消进程,c#,asp.net,multithreading,process,C#,Asp.net,Multithreading,Process,我运行一个进程,在命令行中执行带有参数的exe,它需要时间来完成。同时,我将窗体显示为带有进度条和取消按钮的对话框。按下“取消”按钮时,进程应中止/停止。我有两种方法: A.在主窗体中声明流程类的公共静态对象,并在单击“取消”按钮时从进度窗体中中止该对象: public partial class frmMain : Form { public static Process Process = new Process(); public static bool ExecuteC

我运行一个进程,在命令行中执行带有参数的exe,它需要时间来完成。同时,我将窗体显示为带有进度条和取消按钮的对话框。按下“取消”按钮时,进程应中止/停止。我有两种方法:

A.在主窗体中声明流程类的公共静态对象,并在单击“取消”按钮时从进度窗体中中止该对象:

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 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;
    }
}
并从进度窗口窗体关闭/中止进程:

public partial class frmProgress : Form
{
    private void btnCancel_Click(object sender, EventArgs e)
    {
        frmMain.Process.Close();
        frmMain.Process.Dispose();
    }
}
或者不调用Process.WaitForExit();而是使用Process.HasExited检查流程是否正在运行,如果单击“取消”按钮,则取消该流程:

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 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;
    }
}
正确的方法是什么?

两者的混合

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.HasExit定期轮询是否终止。最好使用一个计时器。我目前还不确定,但可能会有这样的活动


您的第二个解决方案存在一个问题,即它正在积极等待进程完成,同时仍然阻塞用户界面。它使用的是
Application.DoEvents()
,您应该尽量避免使用它,因为它会产生各种令人讨厌的副作用(例如,您可以在递归中多次运行相同的代码)

无需轮询
Process.hasExit
只需执行
frmMain.Process.CanRaiseEvents=true
然后订阅该事件。您的意思是
frmMain.Process.EnableRaisingEvents=true
(而不是
CanRaiseEvents
)?