英語で読む

次の方法で共有


BackgroundWorker クラス

定義

別個のスレッドに対する操作を実行します。

C#
public class BackgroundWorker : IDisposable
C#
public class BackgroundWorker : System.ComponentModel.Component
継承
BackgroundWorker
継承
実装

次のコード例では、時間のかかる操作を BackgroundWorker 非同期的に実行するための クラスの基本を示します。 次の図は、出力の例を示しています。

BackgroundWorker の単純な例

このコードを試すには、Windows フォーム アプリケーションを作成します。 という名前のコントロールをLabel追加し、 と cancelAsyncButtonというresultLabel名前startAsyncButtonの 2 つのButtonコントロールを追加します。 両方のボタンのイベント ハンドラーを作成 Click します。 ツールボックスの [コンポーネント] タブで、 という名前backgroundWorker1のコンポーネントをBackgroundWorker追加します。 の 、ProgressChanged、および RunWorkerCompleted イベント ハンドラーを作成します。BackgroundWorkerDoWork フォームのコードで、既存のコードを次のコードに置き換えます。

C#
using System;
using System.ComponentModel;
using System.Windows.Forms;

namespace BackgroundWorkerSimple
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            backgroundWorker1.WorkerReportsProgress = true;
            backgroundWorker1.WorkerSupportsCancellation = true;
        }

        private void startAsyncButton_Click(object sender, EventArgs e)
        {
            if (backgroundWorker1.IsBusy != true)
            {
                // Start the asynchronous operation.
                backgroundWorker1.RunWorkerAsync();
            }
        }

        private void cancelAsyncButton_Click(object sender, EventArgs e)
        {
            if (backgroundWorker1.WorkerSupportsCancellation == true)
            {
                // Cancel the asynchronous operation.
                backgroundWorker1.CancelAsync();
            }
        }

        // This event handler is where the time-consuming work is done.
        private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
        {
            BackgroundWorker worker = sender as BackgroundWorker;

            for (int i = 1; i <= 10; i++)
            {
                if (worker.CancellationPending == true)
                {
                    e.Cancel = true;
                    break;
                }
                else
                {
                    // Perform a time consuming operation and report progress.
                    System.Threading.Thread.Sleep(500);
                    worker.ReportProgress(i * 10);
                }
            }
        }

        // This event handler updates the progress.
        private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            resultLabel.Text = (e.ProgressPercentage.ToString() + "%");
        }

        // This event handler deals with the results of the background operation.
        private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            if (e.Cancelled == true)
            {
                resultLabel.Text = "Canceled!";
            }
            else if (e.Error != null)
            {
                resultLabel.Text = "Error: " + e.Error.Message;
            }
            else
            {
                resultLabel.Text = "Done!";
            }
        }
    }
}

次のコード例では、時間のかかる操作を BackgroundWorker 非同期的に実行するための クラスの使用を示します。 次の図は、出力の例を示しています。

BackgroundWorker フィボナッチの例

この操作は、選択したフィボナッチ数を計算し、計算の進行に伴う進行状況の更新を報告し、保留中の計算を取り消すことができます。

C#
using System;
using System.Collections;
using System.ComponentModel;
using System.Drawing;
using System.Threading;
using System.Windows.Forms;

namespace BackgroundWorkerExample
{	
    public class FibonacciForm : System.Windows.Forms.Form
    {	
        private int numberToCompute = 0;
        private int highestPercentageReached = 0;

        private System.Windows.Forms.NumericUpDown numericUpDown1;
        private System.Windows.Forms.Button startAsyncButton;
        private System.Windows.Forms.Button cancelAsyncButton;
        private System.Windows.Forms.ProgressBar progressBar1;
        private System.Windows.Forms.Label resultLabel;
        private System.ComponentModel.BackgroundWorker backgroundWorker1;

        public FibonacciForm()
        {	
            InitializeComponent();

            InitializeBackgroundWorker();
        }

        // Set up the BackgroundWorker object by 
        // attaching event handlers. 
        private void InitializeBackgroundWorker()
        {
            backgroundWorker1.DoWork += 
                new DoWorkEventHandler(backgroundWorker1_DoWork);
            backgroundWorker1.RunWorkerCompleted += 
                new RunWorkerCompletedEventHandler(
            backgroundWorker1_RunWorkerCompleted);
            backgroundWorker1.ProgressChanged += 
                new ProgressChangedEventHandler(
            backgroundWorker1_ProgressChanged);
        }
    
        private void startAsyncButton_Click(System.Object sender, 
            System.EventArgs e)
        {
            // Reset the text in the result label.
            resultLabel.Text = String.Empty;

            // Disable the UpDown control until 
            // the asynchronous operation is done.
            this.numericUpDown1.Enabled = false;

            // Disable the Start button until 
            // the asynchronous operation is done.
            this.startAsyncButton.Enabled = false;

            // Enable the Cancel button while 
            // the asynchronous operation runs.
            this.cancelAsyncButton.Enabled = true;

            // Get the value from the UpDown control.
            numberToCompute = (int)numericUpDown1.Value;

            // Reset the variable for percentage tracking.
            highestPercentageReached = 0;

            // Start the asynchronous operation.
            backgroundWorker1.RunWorkerAsync(numberToCompute);
        }

        private void cancelAsyncButton_Click(System.Object sender, 
            System.EventArgs e)
        {   
            // Cancel the asynchronous operation.
            this.backgroundWorker1.CancelAsync();

            // Disable the Cancel button.
            cancelAsyncButton.Enabled = false;
        }

        // This event handler is where the actual,
        // potentially time-consuming work is done.
        private void backgroundWorker1_DoWork(object sender, 
            DoWorkEventArgs e)
        {   
            // Get the BackgroundWorker that raised this event.
            BackgroundWorker worker = sender as BackgroundWorker;

            // Assign the result of the computation
            // to the Result property of the DoWorkEventArgs
            // object. This is will be available to the 
            // RunWorkerCompleted eventhandler.
            e.Result = ComputeFibonacci((int)e.Argument, worker, e);
        }

        // This event handler deals with the results of the
        // background operation.
        private void backgroundWorker1_RunWorkerCompleted(
            object sender, RunWorkerCompletedEventArgs e)
        {
            // First, handle the case where an exception was thrown.
            if (e.Error != null)
            {
                MessageBox.Show(e.Error.Message);
            }
            else if (e.Cancelled)
            {
                // Next, handle the case where the user canceled 
                // the operation.
                // Note that due to a race condition in 
                // the DoWork event handler, the Cancelled
                // flag may not have been set, even though
                // CancelAsync was called.
                resultLabel.Text = "Canceled";
            }
            else
            {
                // Finally, handle the case where the operation 
                // succeeded.
                resultLabel.Text = e.Result.ToString();
            }

            // Enable the UpDown control.
            this.numericUpDown1.Enabled = true;

            // Enable the Start button.
            startAsyncButton.Enabled = true;

            // Disable the Cancel button.
            cancelAsyncButton.Enabled = false;
        }

        // This event handler updates the progress bar.
        private void backgroundWorker1_ProgressChanged(object sender,
            ProgressChangedEventArgs e)
        {
            this.progressBar1.Value = e.ProgressPercentage;
        }

        // This is the method that does the actual work. For this
        // example, it computes a Fibonacci number and
        // reports progress as it does its work.
        long ComputeFibonacci(int n, BackgroundWorker worker, DoWorkEventArgs e)
        {
            // The parameter n must be >= 0 and <= 91.
            // Fib(n), with n > 91, overflows a long.
            if ((n < 0) || (n > 91))
            {
                throw new ArgumentException(
                    "value must be >= 0 and <= 91", "n");
            }

            long result = 0;

            // Abort the operation if the user has canceled.
            // Note that a call to CancelAsync may have set 
            // CancellationPending to true just after the
            // last invocation of this method exits, so this 
            // code will not have the opportunity to set the 
            // DoWorkEventArgs.Cancel flag to true. This means
            // that RunWorkerCompletedEventArgs.Cancelled will
            // not be set to true in your RunWorkerCompleted
            // event handler. This is a race condition.

            if (worker.CancellationPending)
            {   
                e.Cancel = true;
            }
            else
            {   
                if (n < 2)
                {   
                    result = 1;
                }
                else
                {   
                    result = ComputeFibonacci(n - 1, worker, e) + 
                             ComputeFibonacci(n - 2, worker, e);
                }

                // Report progress as a percentage of the total task.
                int percentComplete = 
                    (int)((float)n / (float)numberToCompute * 100);
                if (percentComplete > highestPercentageReached)
                {
                    highestPercentageReached = percentComplete;
                    worker.ReportProgress(percentComplete);
                }
            }

            return result;
        }

        #region Windows Form Designer generated code
        
        private void InitializeComponent()
        {
            this.numericUpDown1 = new System.Windows.Forms.NumericUpDown();
            this.startAsyncButton = new System.Windows.Forms.Button();
            this.cancelAsyncButton = new System.Windows.Forms.Button();
            this.resultLabel = new System.Windows.Forms.Label();
            this.progressBar1 = new System.Windows.Forms.ProgressBar();
            this.backgroundWorker1 = new System.ComponentModel.BackgroundWorker();
            ((System.ComponentModel.ISupportInitialize)(this.numericUpDown1)).BeginInit();
            this.SuspendLayout();
            // 
            // numericUpDown1
            // 
            this.numericUpDown1.Location = new System.Drawing.Point(16, 16);
            this.numericUpDown1.Maximum = new System.Decimal(new int[] {
            91,
            0,
            0,
            0});
            this.numericUpDown1.Minimum = new System.Decimal(new int[] {
            1,
            0,
            0,
            0});
            this.numericUpDown1.Name = "numericUpDown1";
            this.numericUpDown1.Size = new System.Drawing.Size(80, 20);
            this.numericUpDown1.TabIndex = 0;
            this.numericUpDown1.Value = new System.Decimal(new int[] {
            1,
            0,
            0,
            0});
            // 
            // startAsyncButton
            // 
            this.startAsyncButton.Location = new System.Drawing.Point(16, 72);
            this.startAsyncButton.Name = "startAsyncButton";
            this.startAsyncButton.Size = new System.Drawing.Size(120, 23);
            this.startAsyncButton.TabIndex = 1;
            this.startAsyncButton.Text = "Start Async";
            this.startAsyncButton.Click += new System.EventHandler(this.startAsyncButton_Click);
            // 
            // cancelAsyncButton
            // 
            this.cancelAsyncButton.Enabled = false;
            this.cancelAsyncButton.Location = new System.Drawing.Point(153, 72);
            this.cancelAsyncButton.Name = "cancelAsyncButton";
            this.cancelAsyncButton.Size = new System.Drawing.Size(119, 23);
            this.cancelAsyncButton.TabIndex = 2;
            this.cancelAsyncButton.Text = "Cancel Async";
            this.cancelAsyncButton.Click += new System.EventHandler(this.cancelAsyncButton_Click);
            // 
            // resultLabel
            // 
            this.resultLabel.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D;
            this.resultLabel.Location = new System.Drawing.Point(112, 16);
            this.resultLabel.Name = "resultLabel";
            this.resultLabel.Size = new System.Drawing.Size(160, 23);
            this.resultLabel.TabIndex = 3;
            this.resultLabel.Text = "(no result)";
            this.resultLabel.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
            // 
            // progressBar1
            // 
            this.progressBar1.Location = new System.Drawing.Point(18, 48);
            this.progressBar1.Name = "progressBar1";
            this.progressBar1.Size = new System.Drawing.Size(256, 8);
            this.progressBar1.Step = 2;
            this.progressBar1.TabIndex = 4;
            // 
            // backgroundWorker1
            // 
            this.backgroundWorker1.WorkerReportsProgress = true;
            this.backgroundWorker1.WorkerSupportsCancellation = true;
            // 
            // FibonacciForm
            // 
            this.ClientSize = new System.Drawing.Size(292, 118);
            this.Controls.Add(this.progressBar1);
            this.Controls.Add(this.resultLabel);
            this.Controls.Add(this.cancelAsyncButton);
            this.Controls.Add(this.startAsyncButton);
            this.Controls.Add(this.numericUpDown1);
            this.Name = "FibonacciForm";
            this.Text = "Fibonacci Calculator";
            ((System.ComponentModel.ISupportInitialize)(this.numericUpDown1)).EndInit();
            this.ResumeLayout(false);
        }
        #endregion

        [STAThread]
        static void Main()
        {
            Application.Run(new FibonacciForm());
        }
    }
}

注釈

BackgroundWorkerクラスを使用すると、別の専用スレッドで操作を実行できます。 ダウンロードやデータベース トランザクションなどの時間のかかる操作により、ユーザー インターフェイス (UI) が実行中に応答を停止したように見える可能性があります。 応答性の高い UI が必要で、このような操作に関連する長い遅延に直面した場合、クラスは BackgroundWorker 便利なソリューションを提供します。

バックグラウンドで時間のかかる操作を実行するには、 を作成 BackgroundWorker し、操作の進行状況を報告するイベントをリッスンし、操作が完了したときに通知します。 をプログラムで作成することも、ツールボックスの BackgroundWorker [ コンポーネント ] タブからフォームにドラッグ することもできます。 Windows フォーム Designerで をBackgroundWorker作成すると、コンポーネント トレイに表示され、そのプロパティがプロパティ ウィンドウに表示されます。

バックグラウンド操作を設定するには、 イベントのイベント ハンドラーを DoWork 追加します。 このイベント ハンドラーで時間のかかる操作を呼び出します。 操作を開始するには、 を呼び出します RunWorkerAsync。 進行状況の更新の通知を受信するには、 イベントを処理します ProgressChanged 。 操作が完了したときに通知を受信するには、 イベントを処理します RunWorkerCompleted

注意

イベント ハンドラー内のユーザー インターフェイス オブジェクトを操作しないように注意する DoWork 必要があります。 代わりに、 イベントと イベントを介して ProgressChanged ユーザー インターフェイスと RunWorkerCompleted 通信します。

BackgroundWorker イベントは境界を越えて AppDomain マーシャリングされません。 コンポーネントを BackgroundWorker 使用して、複数 AppDomainの でマルチスレッド操作を実行しないでください。

バックグラウンド操作でパラメーターが必要な場合は、 パラメーターを使用して を呼び出 RunWorkerAsync します。 イベント ハンドラー内 DoWork では、 プロパティから パラメーターを DoWorkEventArgs.Argument 抽出できます。

BackgroundWorker の詳細については、「方法:バックグラウンドで操作を実行する」を参照してください。

コンストラクター

BackgroundWorker()

BackgroundWorker クラスの新しいインスタンスを初期化します。

プロパティ

CancellationPending

アプリケーションがバックグラウンド操作のキャンセルを要求したかどうかを示す値を取得します。

CanRaiseEvents

コンポーネントがイベントを発生させることがきるかどうかを示す値を取得します。

(継承元 Component)
Container

IContainer を含む Component を取得します。

(継承元 Component)
DesignMode

Component が現在デザイン モードかどうかを示す値を取得します。

(継承元 Component)
Events

Component に結び付けられているイベント ハンドラーのリストを取得します。

(継承元 Component)
IsBusy

BackgroundWorker が非同期操作を実行中かどうかを示す値を取得します。

Site

ComponentISite を取得または設定します。

(継承元 Component)
WorkerReportsProgress

BackgroundWorker が進行状況の更新を報告できるかどうかを示す値を取得または設定します。

WorkerSupportsCancellation

BackgroundWorker が非同期のキャンセルをサポートしているかどうかを示す値を取得または設定します。

メソッド

CancelAsync()

保留中のバックグラウンド操作のキャンセルを要求します。

CreateObjRef(Type)

リモート オブジェクトとの通信に使用するプロキシの生成に必要な情報をすべて格納しているオブジェクトを作成します。

(継承元 MarshalByRefObject)
Dispose()

アンマネージ リソースの解放またはリセットに関連付けられているアプリケーション定義のタスクを実行します。

Dispose()

Component によって使用されているすべてのリソースを解放します。

(継承元 Component)
Dispose(Boolean)

このメソッドは何も実行しません。

Dispose(Boolean)

Component によって使用されているアンマネージド リソースを解放し、オプションでマネージド リソースも解放します。

(継承元 Component)
Equals(Object)

指定されたオブジェクトが現在のオブジェクトと等しいかどうかを判断します。

(継承元 Object)
GetHashCode()

既定のハッシュ関数として機能します。

(継承元 Object)
GetLifetimeService()
古い.

対象のインスタンスの有効期間ポリシーを制御する、現在の有効期間サービス オブジェクトを取得します。

(継承元 MarshalByRefObject)
GetService(Type)

Component またはその Container で提供されるサービスを表すオブジェクトを返します。

(継承元 Component)
GetType()

現在のインスタンスの Type を取得します。

(継承元 Object)
InitializeLifetimeService()
古い.

このインスタンスの有効期間ポリシーを制御する有効期間サービス オブジェクトを取得します。

(継承元 MarshalByRefObject)
MemberwiseClone()

現在の Object の簡易コピーを作成します。

(継承元 Object)
MemberwiseClone(Boolean)

現在の MarshalByRefObject オブジェクトの簡易コピーを作成します。

(継承元 MarshalByRefObject)
OnDoWork(DoWorkEventArgs)

DoWork イベントを発生させます。

OnProgressChanged(ProgressChangedEventArgs)

ProgressChanged イベントを発生させます。

OnRunWorkerCompleted(RunWorkerCompletedEventArgs)

RunWorkerCompleted イベントを発生させます。

ReportProgress(Int32)

ProgressChanged イベントを発生させます。

ReportProgress(Int32, Object)

ProgressChanged イベントを発生させます。

RunWorkerAsync()

バックグラウンド操作の実行を開始します。

RunWorkerAsync(Object)

バックグラウンド操作の実行を開始します。

ToString()

現在のオブジェクトを表す文字列を返します。

(継承元 Object)
ToString()

Component の名前 (存在する場合) を格納する String を返します。 このメソッドはオーバーライドできません。

(継承元 Component)

イベント

Disposed

Dispose() メソッドの呼び出しによってコンポーネントが破棄されるときに発生します。

(継承元 Component)
DoWork

RunWorkerAsync() が呼び出されたときに発生します。

ProgressChanged

ReportProgress(Int32) が呼び出されたときに発生します。

RunWorkerCompleted

バックグラウンド操作の完了時、キャンセル時、またはバックグラウンド操作によって例外が発生したときに発生します。

適用対象

製品 バージョン
.NET Core 1.0, Core 1.1, Core 2.0, Core 2.1, Core 2.2, Core 3.0, Core 3.1, 5, 6, 7, 8, 9
.NET Framework 2.0, 3.0, 3.5, 4.0, 4.5, 4.5.1, 4.5.2, 4.6, 4.6.1, 4.6.2, 4.7, 4.7.1, 4.7.2, 4.8, 4.8.1
.NET Standard 2.0, 2.1
UWP 10.0

こちらもご覧ください