我运行一个在命令行中使用参数执行exe的进程,并且需要一些时间才能完成。在此期间,我将表单显示为带有进度条和取消按钮的对话框。按下取消按钮时,该过程应该中止/停止。我有两种方法可以做到:
一个。在主窗体中声明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;
}
}
这样做的正确方法是什么?
答案 0 :(得分:6)
两者的混合。
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()
,你应该尽量避免它,因为它会产生各种令人讨厌的副作用(例如,你可以在递归中运行多次相同的代码)。