[C#] ProgressBarとBackgroundWorkerの連携方法

C#でProgressBarBackgroundWorkerを連携させる方法は、非同期処理中に進捗をユーザーに示すために用いられます。

BackgroundWorkerはバックグラウンドで作業を行い、ProgressChangedイベントを通じて進捗を報告します。

まず、BackgroundWorkerWorkerReportsProgressプロパティをtrueに設定します。

次に、DoWorkイベントで長時間の処理を実行し、ReportProgressメソッドを使って進捗を報告します。

ProgressChangedイベントハンドラーでProgressBarValueプロパティを更新し、進捗を視覚的に表示します。

これにより、ユーザーは処理の進行状況をリアルタイムで確認できます。

この記事でわかること
  • ProgressBarとBackgroundWorkerの基本的な使い方
  • 非同期処理の実装手順
  • 進捗状況の報告方法
  • 複数のProgressBarの連携方法
  • キャンセル機能とエラーハンドリングの実装方法

目次から探す

ProgressBarとBackgroundWorkerの基本

C#のWindowsフォームアプリケーションにおいて、ユーザーに進捗状況を示すために使用されるのがProgressBarです。

ProgressBarは、処理の進行状況を視覚的に表示するためのコントロールで、特に時間のかかる処理を行う際に役立ちます。

一方、BackgroundWorkerは、非同期処理を簡単に実装するためのクラスで、UIスレッドをブロックせずにバックグラウンドで処理を実行することができます。

この二つを組み合わせることで、ユーザーにスムーズな操作体験を提供しつつ、処理の進捗をリアルタイムで表示することが可能になります。

この記事では、ProgressBarとBackgroundWorkerの連携方法について詳しく解説します。

ProgressBarの設定

ProgressBarの基本プロパティ

ProgressBarには、いくつかの基本的なプロパティがあります。

これらのプロパティを設定することで、ProgressBarの表示や動作をカスタマイズできます。

主なプロパティは以下の通りです。

スクロールできます
プロパティ名説明
MinimumProgressBarの最小値を設定します。
MaximumProgressBarの最大値を設定します。
Value現在の進捗状況を設定します。
Step進捗を増加させる際のステップ値を設定します。
StyleProgressBarのスタイルを設定します。

ProgressBarのスタイル設定

ProgressBarのスタイルは、表示方法を変更するために使用されます。

主に以下の2つのスタイルがあります。

スクロールできます
スタイル名説明
Blocksブロック状に進捗を表示します。
Continuous滞りなく進捗を表示します。

スタイルは、ProgressBar.Styleプロパティを使用して設定できます。

例えば、以下のように設定します。

progressBar1.Style = ProgressBarStyle.Continuous; // 滞りなく進捗を表示

ProgressBarの初期化

ProgressBarを使用するには、まずフォームの初期化時に設定を行います。

以下は、ProgressBarの初期化の例です。

partial class MyForm : Form
{
    private ProgressBar progressBar1;
    public MyForm()
    {
        InitializeComponent(); // フォームの初期化
        InitializeProgressBar(); // ProgressBarの初期化
    }
    private void InitializeProgressBar()
    {
        progressBar1 = new ProgressBar(); // ProgressBarのインスタンスを作成
        progressBar1.Minimum = 0; // 最小値を設定
        progressBar1.Maximum = 100; // 最大値を設定
        progressBar1.Value = 0; // 初期値を設定
        progressBar1.Style = ProgressBarStyle.Continuous; // スタイルを設定
        this.Controls.Add(progressBar1); // フォームに追加
    }
}

このコードでは、ProgressBarの最小値、最大値、初期値、スタイルを設定し、フォームに追加しています。

これにより、ProgressBarが正しく表示されるようになります。

BackgroundWorkerの設定

BackgroundWorkerの基本プロパティ

BackgroundWorkerは、非同期処理を簡単に実装するためのクラスです。

以下の基本プロパティを使用して、BackgroundWorkerの動作を設定できます。

スクロールできます
プロパティ名説明
WorkerReportsProgress進捗状況を報告するかどうかを設定します。
WorkerSupportsCancellation処理のキャンセルをサポートするかどうかを設定します。

これらのプロパティを適切に設定することで、BackgroundWorkerの機能を最大限に活用できます。

DoWorkイベントの設定

DoWorkイベントは、バックグラウンドで実行される処理を定義するためのイベントです。

このイベント内で、時間のかかる処理を実行します。

以下は、DoWorkイベントの設定例です。

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
    for (int i = 0; i <= 100; i++)
    {
        // 進捗状況を報告
        backgroundWorker1.ReportProgress(i);
        // 処理の遅延をシミュレート
        System.Threading.Thread.Sleep(50); // 50ミリ秒待機
    }
}

このコードでは、0から100までの進捗を報告しながら、50ミリ秒の遅延をシミュレートしています。

ProgressChangedイベントの設定

ProgressChangedイベントは、DoWorkイベントで報告された進捗状況を受け取るためのイベントです。

このイベント内で、ProgressBarの値を更新します。

以下は、ProgressChangedイベントの設定例です。

private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
    progressBar1.Value = e.ProgressPercentage; // ProgressBarの値を更新
}

このコードでは、ProgressChangedイベントが発生した際に、ProgressBarの値を更新しています。

RunWorkerCompletedイベントの設定

RunWorkerCompletedイベントは、バックグラウンド処理が完了した後に実行されるイベントです。

このイベント内で、処理が完了したことをユーザーに通知したり、UIを更新したりします。

以下は、RunWorkerCompletedイベントの設定例です。

private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    MessageBox.Show("処理が完了しました!"); // 処理完了のメッセージを表示
}

このコードでは、バックグラウンド処理が完了した際に、メッセージボックスを表示してユーザーに通知しています。

これにより、ユーザーは処理の完了を確認できます。

ProgressBarとBackgroundWorkerの連携手順

BackgroundWorkerの初期化

ProgressBarとBackgroundWorkerを連携させるためには、まずBackgroundWorkerを初期化し、必要なイベントハンドラを設定します。

以下は、BackgroundWorkerの初期化の例です。

partial class MyForm : Form
{
    private BackgroundWorker backgroundWorker1;
    public MyForm()
    {
        InitializeComponent(); // フォームの初期化
        InitializeBackgroundWorker(); // BackgroundWorkerの初期化
    }
    private void InitializeBackgroundWorker()
    {
        backgroundWorker1 = new BackgroundWorker(); // BackgroundWorkerのインスタンスを作成
        backgroundWorker1.WorkerReportsProgress = true; // 進捗報告を有効にする
        backgroundWorker1.WorkerSupportsCancellation = true; // キャンセルをサポートする
        backgroundWorker1.DoWork += backgroundWorker1_DoWork; // DoWorkイベントの設定
        backgroundWorker1.ProgressChanged += backgroundWorker1_ProgressChanged; // ProgressChangedイベントの設定
        backgroundWorker1.RunWorkerCompleted += backgroundWorker1_RunWorkerCompleted; // RunWorkerCompletedイベントの設定
    }
}

このコードでは、BackgroundWorkerのインスタンスを作成し、進捗報告とキャンセルをサポートするように設定しています。

また、各イベントハンドラを設定しています。

DoWorkイベントでの非同期処理

DoWorkイベントでは、実際の非同期処理を実行します。

ここでは、時間のかかる処理を行い、その進捗を報告します。

以下は、DoWorkイベントの実装例です。

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
    for (int i = 0; i <= 100; i++)
    {
        // 進捗状況を報告
        backgroundWorker1.ReportProgress(i);
        // 処理の遅延をシミュレート
        System.Threading.Thread.Sleep(50); // 50ミリ秒待機
    }
}

このコードでは、0から100までの進捗を報告しながら、50ミリ秒の遅延をシミュレートしています。

ReportProgressメソッドの使用

ReportProgressメソッドは、進捗状況を報告するために使用します。

このメソッドを呼び出すことで、ProgressChangedイベントが発生し、ProgressBarの更新が行われます。

以下は、ReportProgressメソッドの使用例です。

backgroundWorker1.ReportProgress(i); // iの値を進捗として報告

このコードは、DoWorkイベント内で進捗を報告する際に使用されます。

ProgressChangedイベントでのProgressBar更新

ProgressChangedイベントでは、報告された進捗状況を受け取り、ProgressBarの値を更新します。

以下は、ProgressChangedイベントの実装例です。

private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
    progressBar1.Value = e.ProgressPercentage; // ProgressBarの値を更新
}

このコードでは、ProgressChangedイベントが発生した際に、ProgressBarの値を更新しています。

これにより、ユーザーは処理の進捗をリアルタイムで確認することができます。

以上の手順を踏むことで、ProgressBarとBackgroundWorkerを連携させ、スムーズなユーザー体験を提供することができます。

実装例

シンプルなファイルコピーの進捗表示

ファイルコピー処理を行う際に、ProgressBarを使用して進捗を表示する例です。

以下のコードでは、指定したファイルをコピーし、その進捗をProgressBarで表示します。

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
    string sourceFile = "source.txt"; // コピー元ファイル
    string destinationFile = "destination.txt"; // コピー先ファイル
    FileInfo fileInfo = new FileInfo(sourceFile);
    long totalBytes = fileInfo.Length; // ファイルの総バイト数
    long bytesCopied = 0; // コピーしたバイト数
    using (FileStream sourceStream = new FileStream(sourceFile, FileMode.Open))
    using (FileStream destinationStream = new FileStream(destinationFile, FileMode.Create))
    {
        byte[] buffer = new byte[1024]; // 1KBのバッファ
        int bytesRead;
        while ((bytesRead = sourceStream.Read(buffer, 0, buffer.Length)) > 0)
        {
            destinationStream.Write(buffer, 0, bytesRead); // バッファの内容をコピー
            bytesCopied += bytesRead; // コピーしたバイト数を更新
            int progressPercentage = (int)((bytesCopied * 100) / totalBytes); // 進捗率を計算
            backgroundWorker1.ReportProgress(progressPercentage); // 進捗を報告
        }
    }
}

このコードでは、ファイルを1KBずつ読み込み、コピーしながら進捗を報告しています。

データベース処理の進捗表示

データベースに大量のデータを挿入する際に、ProgressBarを使用して進捗を表示する例です。

以下のコードでは、データベースに1000件のデータを挿入し、その進捗を表示します。

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
    using (SqlConnection connection = new SqlConnection("your_connection_string"))
    {
        connection.Open();
        for (int i = 1; i <= 1000; i++)
        {
            // データを挿入するSQL文
            string query = "INSERT INTO YourTable (Column1) VALUES (@Value)";
            using (SqlCommand command = new SqlCommand(query, connection))
            {
                command.Parameters.AddWithValue("@Value", i);
                command.ExecuteNonQuery(); // データを挿入
            }
            int progressPercentage = (int)((i * 100) / 1000); // 進捗率を計算
            backgroundWorker1.ReportProgress(progressPercentage); // 進捗を報告
        }
    }
}

このコードでは、データベースにデータを挿入しながら進捗を報告しています。

ネットワークダウンロードの進捗表示

ネットワークからファイルをダウンロードする際に、ProgressBarを使用して進捗を表示する例です。

以下のコードでは、指定したURLからファイルをダウンロードし、その進捗を表示します。

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
    string url = "http://example.com/largefile.zip"; // ダウンロードするファイルのURL
    string destinationFile = "largefile.zip"; // 保存先ファイル
    using (WebClient webClient = new WebClient())
    {
        webClient.DownloadProgressChanged += (s, ev) =>
        {
            backgroundWorker1.ReportProgress(ev.ProgressPercentage); // 進捗を報告
        };
        webClient.DownloadFile(url, destinationFile); // ファイルをダウンロード
    }
}

このコードでは、WebClientを使用してファイルをダウンロードし、DownloadProgressChangedイベントで進捗を報告しています。

これにより、ユーザーはダウンロードの進捗をリアルタイムで確認できます。

応用例

複数のProgressBarとBackgroundWorkerの連携

複数のProgressBarを使用して、異なる処理の進捗を同時に表示する例です。

以下のコードでは、2つのBackgroundWorkerを使用して、それぞれ異なるファイルコピー処理の進捗を表示します。

private void InitializeBackgroundWorkers()
{
    backgroundWorker1 = new BackgroundWorker();
    backgroundWorker1.WorkerReportsProgress = true;
    backgroundWorker1.DoWork += backgroundWorker1_DoWork1;
    backgroundWorker1.ProgressChanged += backgroundWorker1_ProgressChanged1;
    backgroundWorker2 = new BackgroundWorker();
    backgroundWorker2.WorkerReportsProgress = true;
    backgroundWorker2.DoWork += backgroundWorker2_DoWork2;
    backgroundWorker2.ProgressChanged += backgroundWorker2_ProgressChanged2;
}
private void backgroundWorker1_DoWork1(object sender, DoWorkEventArgs e)
{
    // ファイルコピー処理1
}
private void backgroundWorker2_DoWork2(object sender, DoWorkEventArgs e)
{
    // ファイルコピー処理2
}
private void backgroundWorker1_ProgressChanged1(object sender, ProgressChangedEventArgs e)
{
    progressBar1.Value = e.ProgressPercentage; // ProgressBar1の更新
}
private void backgroundWorker2_ProgressChanged2(object sender, ProgressChangedEventArgs e)
{
    progressBar2.Value = e.ProgressPercentage; // ProgressBar2の更新
}

このコードでは、2つのBackgroundWorkerを初期化し、それぞれの進捗を異なるProgressBarで表示しています。

キャンセル機能の実装

ユーザーが処理をキャンセルできるようにするための実装例です。

以下のコードでは、キャンセルボタンを押すことで、BackgroundWorkerの処理をキャンセルします。

private void cancelButton_Click(object sender, EventArgs e)
{
    if (backgroundWorker1.IsBusy)
    {
        backgroundWorker1.CancelAsync(); // 処理をキャンセル
    }
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
    for (int i = 0; i <= 100; i++)
    {
        if (backgroundWorker1.CancellationPending) // キャンセルが要求された場合
        {
            e.Cancel = true; // 処理をキャンセル
            return;
        }
        // 進捗を報告
        backgroundWorker1.ReportProgress(i);
        System.Threading.Thread.Sleep(50); // 処理の遅延をシミュレート
    }
}

このコードでは、キャンセルボタンが押された際に、BackgroundWorkerの処理をキャンセルする機能を実装しています。

エラーハンドリングの実装

処理中にエラーが発生した場合に備えて、エラーハンドリングを実装する例です。

以下のコードでは、DoWorkイベント内で例外が発生した場合に、RunWorkerCompletedイベントでエラーメッセージを表示します。

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
    try
    {
        // 何らかの処理
        throw new Exception("エラーが発生しました!"); // シミュレーション
    }
    catch (Exception ex)
    {
        e.Result = ex.Message; // エラーメッセージを保存
    }
}
private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    if (e.Error != null) // エラーが発生した場合
    {
        MessageBox.Show("エラー: " + e.Error.Message); // エラーメッセージを表示
    }
    else if (e.Cancelled) // 処理がキャンセルされた場合
    {
        MessageBox.Show("処理がキャンセルされました。"); // キャンセルメッセージを表示
    }
    else // 正常に完了した場合
    {
        MessageBox.Show("処理が完了しました!"); // 完了メッセージを表示
    }
}

このコードでは、DoWorkイベント内で例外が発生した場合に、そのエラーメッセージをRunWorkerCompletedイベントで表示しています。

これにより、ユーザーはエラーの内容を確認することができます。

よくある質問

ProgressBarが更新されないのはなぜ?

ProgressBarが更新されない原因はいくつか考えられます。

主な理由は以下の通りです。

  • UIスレッドのブロック: 長時間実行される処理がUIスレッドで行われている場合、UIが更新されずProgressBarも動かなくなります。

BackgroundWorkerを使用して非同期処理を行うことで解決できます。

  • ReportProgressメソッドの未使用: ProgressBarの値を更新するためには、必ずReportProgressメソッドを呼び出す必要があります。

このメソッドを使用して進捗を報告しているか確認してください。

  • ProgressChangedイベントの未設定: ProgressChangedイベントが正しく設定されていない場合、ProgressBarの更新が行われません。

イベントハンドラが正しく設定されているか確認しましょう。

BackgroundWorkerの処理が遅い場合の対処法は?

BackgroundWorkerの処理が遅い場合、以下の対処法を検討できます。

  • 処理の最適化: 処理内容を見直し、無駄な計算や処理を削減することで、全体の処理時間を短縮できます。
  • バッファサイズの調整: ファイルコピーやデータベース処理などでバッファを使用している場合、バッファサイズを調整することでパフォーマンスが向上することがあります。
  • 非同期処理の見直し: BackgroundWorkerの代わりにTaskasync/awaitを使用することで、より効率的な非同期処理が可能です。

これにより、UIの応答性も向上します。

キャンセルボタンを実装するにはどうすればいい?

キャンセルボタンを実装するためには、以下の手順を行います。

  1. キャンセルボタンの作成: フォームにキャンセルボタンを追加します。
  2. キャンセルボタンのイベントハンドラを設定: ボタンがクリックされた際に、BackgroundWorkerのCancelAsyncメソッドを呼び出すイベントハンドラを作成します。
  3. DoWorkイベント内でキャンセルの確認: DoWorkイベント内でCancellationPendingプロパティを確認し、キャンセルが要求された場合は処理を中断します。

以下は、キャンセルボタンの実装例です。

private void cancelButton_Click(object sender, EventArgs e)
{
    if (backgroundWorker1.IsBusy)
    {
        backgroundWorker1.CancelAsync(); // 処理をキャンセル
    }
}

このように実装することで、ユーザーがキャンセルボタンを押すことで、実行中の処理を中断できるようになります。

まとめ

この記事では、C#のWindowsフォームアプリケーションにおけるProgressBarとBackgroundWorkerの連携方法について詳しく解説しました。

ProgressBarを使用することで、ユーザーに処理の進捗を視覚的に示すことができ、BackgroundWorkerを利用することで、UIをブロックせずに非同期処理を実行することが可能です。

これらの技術を活用することで、よりスムーズで快適なユーザー体験を提供できるようになりますので、ぜひ実際のプロジェクトに取り入れてみてください。

当サイトはリンクフリーです。出典元を明記していただければ、ご自由に引用していただいて構いません。

関連カテゴリーから探す

  • URLをコピーしました!
目次から探す