バックグラウンドワーカー

# BackgroundWorker を使用してタスクを完了します。

次の例は、BackgroundWorker を使用して WinForms ProgressBar を更新する方法を示しています。 backgroundWorker は、UI スレッドをブロックせずにプログレス バーの値を更新するため、バックグラウンドで作業が行われている間、リアクティブ UI が表示されます。

namespace BgWorkerExample
{
    public partial class Form1 : Form
{

    //a new instance of a backgroundWorker is created.
    BackgroundWorker bgWorker = new BackgroundWorker();
    
    public Form1()
    {
        InitializeComponent();

        prgProgressBar.Step = 1;

        //this assigns event handlers for the backgroundWorker
        bgWorker.DoWork += bgWorker_DoWork;
        bgWorker.RunWorkerCompleted += bgWorker_WorkComplete;

        //tell the backgroundWorker to raise the "DoWork" event, thus starting it.
        //Check to make sure the background worker is not already running.
        if(!bgWorker.IsBusy)
            bgWorker.RunWorkerAsync();
        
    }

    private void bgWorker_DoWork(object sender, DoWorkEventArgs e)
    {
        //this is the method that the backgroundworker will perform on in the background thread.
        /* One thing to note! A try catch is not necessary as any exceptions will terminate the backgroundWorker and report 
          the error to the "RunWorkerCompleted" event */
        CountToY();    
    }

    private void bgWorker_WorkComplete(object sender, RunWorkerCompletedEventArgs e)
    {
        //e.Error will contain any exceptions caught by the backgroundWorker
        if (e.Error != null)
        {
            MessageBox.Show(e.Error.Message);
        }
        else
        {
            MessageBox.Show("Task Complete!");
            prgProgressBar.Value = 0;
        }
    }

    // example method to perform a "long" running task.
    private void CountToY()
    {
        int x = 0;

        int maxProgress = 100;
        prgProgressBar.Maximum = maxProgress;
        

        while (x < maxProgress)
        {
            System.Threading.Thread.Sleep(50);
            Invoke(new Action(() => { prgProgressBar.PerformStep(); }));
            x += 1;
        }
    }


}

<強い>

結果は次のとおりです...

# イベント ハンドラーを BackgroundWorker に割り当てる

BackgroundWorker のインスタンスが宣言されたら、実行するタスクのプロパティとイベント ハンドラーを指定する必要があります。


   /* This is the backgroundworker's "DoWork" event handler. This 
       method is what will contain all the work you 
       wish to have your program perform without blocking the UI. */

    bgWorker.DoWork += bgWorker_DoWork;


    /*This is how the DoWork event method signature looks like:*/
    private void bgWorker_DoWork(object sender, DoWorkEventArgs e)
    {
        // Work to be done here   
        // ...
        // To get a reference to the current Backgroundworker:
        BackgroundWorker worker = sender as BackgroundWorker;
        // The reference to the BackgroundWorker is often used to report progress
        worker.ReportProgress(...);
    }

    /*This is the method that will be run once the BackgroundWorker has completed its tasks */

    bgWorker.RunWorkerCompleted += bgWorker_CompletedWork;

    /*This is how the RunWorkerCompletedEvent event method signature looks like:*/
    private void bgWorker_CompletedWork(object sender, RunWorkerCompletedEventArgs e)
    {
        // Things to be done after the backgroundworker has finished
    }

   /* When you wish to have something occur when a change in progress 
     occurs, (like the completion of a specific task) the "ProgressChanged" 
     event handler is used. Note that ProgressChanged events may be invoked
     by calls to bgWorker.ReportProgress(...) only if bgWorker.WorkerReportsProgress
     is set to true.  */

     bgWorker.ProgressChanged += bgWorker_ProgressChanged;

    /*This is how the ProgressChanged event method signature looks like:*/
    private void bgWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
    {
        // Things to be done when a progress change has been reported

        /* The ProgressChangedEventArgs gives access to a percentage,
         allowing for easy reporting of how far along a process is*/
        int progress = e.ProgressPercentage;
    }

# 新しい BackgroundWorker インスタンスの作成

BackgroundWorker は一般的に、UI スレッドをブロックすることなく、時間のかかるタスクを実行するために使用されます。

// BackgroundWorker is part of the ComponentModel namespace.
using System.ComponentModel;

namespace BGWorkerExample 
{
     public partial class ExampleForm : Form 
     {

      // the following creates an instance of the BackgroundWorker named "bgWorker"
      BackgroundWorker bgWorker = new BackgroundWorker();

      public ExampleForm() { ...

# プロパティを BackgroundWorker に割り当てる

これにより、タスク間で BackgroundWorker をキャンセルできます

bgWorker.WorkerSupportsCancellation = true;

これにより、ワーカーはタスクの完了までの進捗状況を報告できます...

bgWorker.WorkerReportsProgress = true;

//this must also be used in conjunction with the ProgressChanged event

# 構文

  • `bgWorker.CancellationPending //操作中に bgWorker がキャンセルされたかどうかを返します`
  • `bgWorker.IsBusy //bgWorker が動作中の場合は true を返します`
  • `bgWorker.ReportProgress(int x) //進行中の変更を報告します。 「ProgressChanged」イベントを発生させます`
  • `bgWorker.RunWorkerAsync() //「DoWork」イベントを発生させて BackgroundWorker を開始します`
  • `bgWorker.CancelAsync() //タスクの完了後に停止するように BackgroundWorker に指示します。`
  • # コメント

    UI スレッド内で長時間実行される操作を実行すると、アプリケーションが応答しなくなり、アプリケーションが動作を停止したようにユーザーに表示される可能性があります。これらのタスクはバックグラウンド スレッドで実行することをお勧めします。完了したら、UI を更新できます。

    BackgroundWorker の操作中に UI を変更するには、通常、更新するコントロールで Control.Invoke メソッドを使用して、UI スレッドへの変更を呼び出す必要があります。これを怠ると、プログラムで例外がスローされます。

    BackgroundWorker は通常、Windows フォーム アプリケーションでのみ使用されます。 WPF アプリケーションでは、作業をバックグラウンド スレッドにオフロードするために Task が使用されます (おそらく async/await と組み合わせて)。 UI スレッドへの更新のマーシャリングは通常、更新されるプロパティが INotifyPropertyChanged を実装するときに自動的に行われるか、UI スレッドの Dispatcher を使用して手動で行われます。