このページの最終更新日 2020/10/25

WindowsFromアプリケーションの中断処理

1. 中断処理を実装しよう

 Windowsフォームアプリケーションにおいて実行処理が長い場合、実行途中にユーザーが入力情報に誤りがあることに気づくなどして、一時中断処理を求められることがあります。タスクマネージャを起動して実行中のアプリを強制終了することは出来ますが、実行中のアプリが他のアプリのライセンスを掴んでいる場合は適切にライセンスの解放処理を行う必要があるなど、アプリを強制終了することは問題となる場面が多く存在します。
 そこでアプリのGUIに中止操作を行うボタンを用意しておき、ユーザーがこのボタンを押したときは、アプリを中止すると共にライセンスの解放処理などを適切に行ってやる必要があります。

 ここで、単純な例として100ミリ秒毎にプログレスバーの値を1ずつ上げていくプログラムを考えます。プログレスバーのMaxは100であり、10秒間かけてプログレスバーの値を更新していきます。以下は、プログレスバーの更新途中に「中止」ボタンを押下することでプログレスバーの更新を中断しようと意図したプログラムですが、これでは上手くいきません。メインのスレッドが終了するまで「中止」ボタンは押下出来ないからです。

プログレスバーを更新するプログラム

- pic.1 -


番号コントロール名前
[1]ProgressBarpbWork
[2]ButtonbtnExe
[3]ButtonbtnCancel

- code.1 -
public partial class FormMain : Form //注:このコードは駄目な例ですが、このコードを元に話を進めるので書いてみましょう。
{
    private bool _isCancelled;

    public FormMain()
    {
        InitializeComponent();
        this.btnExe.Click += new EventHandler(BtnExeClick);
        this.btnCancel.Click += new EventHandler(BtnCancelClick);
    }

    private void BtnExeClick(object sender, EventArgs e)
    {
        try
        {
            for (int iProg = 1; iProg <= 100; iProg++)
            {
                Task.Delay(100).Wait();
                if (_isCancelled) { throw new Exception("ユーザー操作により中止されました。"); }
                this.pbWork.Value = iProg;
            }
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.Message, "エラー", MessageBoxButtons.OK, MessageBoxIcon.Error);
        }
    }

    private void BtnCancelClick(object sender, EventArgs e)
    {
        _isCancelled = true;
    }
} 

 これを解決するためにはマルチスレッドを使うのがお作法です。.NETではマルチスレッド処理を行うためのクラスとして、Thread, ThreadPool, Task, BackgroundWorkerなどが用意されています。ここでは「task」と「BackgroundWorker」について説明していきたいと思います。