8

コマンド ラインで引数を指定して exe を実行するプロセスを実行すると、完了するまでに時間がかかります。その間、進行状況バーとキャンセル ボタンを含むダイアログとしてフォームを表示します。キャンセルボタンが押されると、プロセスは中止/停止する必要があります。私はそれを行うには2つの方法があります:

A. メイン フォームで Process クラスの public static オブジェクトを宣言し、キャンセル ボタンがクリックされたときに進行状況フォームから中止します。

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;
    }
}

それを行う正しい方法は何ですか?

4

1 に答える 1

8

2つのミックス。

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 を定期的に使用して、終了をポーリングします。これにはタイマーを使用するのが最善です。現時点では定かではありませんが、イベントが開催される可能性もあります。

2 番目の解決策には、プロセスが終了するのを積極的に待っている一方で、ユーザー インターフェイスをまだブロックしているという問題があります。そして、これはApplication.DoEvents()あらゆる種類の厄介な副作用を引き起こすため、絶対に避けるべき使用です (たとえば、再帰で同じコードを数回実行できるようになります)。

于 2013-10-29T13:04:33.030 に答える