ComboBox のリストに多くの要素を追加すると処理に時間がかかる

ComboBox のリストに多くの要素を追加すると処理に時間がかかる現象の対処法を紹介します。

概要

ComboBoxのドロップダウンリストに多くの項目を単純に追加すると処理に時間がかります。
ドロップダウンリストに多くの項目を追加する場合は、BeginUpdate()メソッドを利用します。

単純な実装での現象の確認

単純な実装でどの程度の時間がかかるか確認します。以下のプログラムを作成します。

UI

下図のフォームを作成します。Combobox, Button, 複数行のTextBoxを配置します。
ComboBox のリストに多くの要素を追加すると処理に時間がかかる:画像1

コード

下記のコードを記述します。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace ComboBoxDemo
{
  public partial class FormManyAdd : Form
  {
    public FormManyAdd()
    {
      InitializeComponent();
    }

    private void button1_Click(object sender, EventArgs e)
    {
      System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
      sw.Start();
      for (int i = 0; i < 30000; i++) {
        comboBox1.Items.Add("Item:"+i.ToString());
      }
      textBox1.Text += string.Format("処理終了:{0:d}", sw.ElapsedMilliseconds);
    }
  }
}

解説

処理にかかった時間を計測するため、Stopwatchクラスを利用して処理時間を計測します。Stopwatchクラスの利用については こちらの記事を参照して下さい。
処理の終了後処理にかかった時間をTextBoxに表示します。

  System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
  sw.Start();
  /*
    中略
  */
  textBox1.Text += string.Format("処理終了:{0:d}", sw.ElapsedMilliseconds);


下記コードでコンボボックスのドロップダウンリストに項目を追加します。今回の例では30,000個要素を追加します。
コンボボックスへの項目追加はこちらの記事も参照してください。

  for (int i = 0; i < 30000; i++) {
    comboBox1.Items.Add("Item:"+i.ToString());
  }

実行結果

プロジェクトを実行します。下図のウィンドウが表示されます。
ComboBox のリストに多くの要素を追加すると処理に時間がかかる:画像2

[button1]をクリックします。コンボボックスに項目が追加されます。追加処理が完了すると、処理に要した時間がテキストボックスに表示されます。 今回の処理は2,869ミリ秒(=2.8秒)かかっていることがわかります。
ComboBox のリストに多くの要素を追加すると処理に時間がかかる:画像3

コンボボックスのドロップダウンリストを確認すると、30,000個アイテムが追加されていることが確認できます。
ComboBox のリストに多くの要素を追加すると処理に時間がかかる:画像4

BeginUpdate, EndUpdate を利用して高速に要素を追加する

BeginUpdate, EndUpdate メソッドを利用してコンボボックスへの項目の追加を高速に処理します。

UI

下図のフォームを作成します。Combobox, Buttonを2つ, 複数行のTextBoxを配置します。

ComboBox のリストに多くの要素を追加すると処理に時間がかかる:画像5

コード

下記のコードを記述します。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace ComboBoxDemo
{
  public partial class FormManyAdd : Form
  {
    public FormManyAdd()
    {
      InitializeComponent();
    }

    private void button1_Click(object sender, EventArgs e)
    {
      System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
      sw.Start();
      for (int i = 0; i < 30000; i++) {
        comboBox1.Items.Add("Item:"+i.ToString());
      }
      textBox1.Text += string.Format("処理終了:{0:d}", sw.ElapsedMilliseconds);
    }

    private void button2_Click(object sender, EventArgs e)
    {
      System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
      sw.Start();
      comboBox1.BeginUpdate();
      for (int i = 0; i < 30000; i++) {
        comboBox1.Items.Add("Item:" + i.ToString());
      }
      comboBox1.EndUpdate();

      textBox1.Text += string.Format("処理終了:{0:d}", sw.ElapsedMilliseconds);
    }
  }
}

解説

button1は先のプログラム例のコードと同様です。
button2のコードもbutton1と同様ですが、コンボボックスに要素を追加する前にBeginUpdateメソッドを呼び出し、処理の追加後にEndUpdateメソッドを 呼び出しています。

BeginUpdate, EndUpdateの処理の意味

BeginUpdateメソッドが呼び出されると、コントロールは更新処理が発生する状態に設定されるため、コントロールの描画処理を停止します。
EndUpdateメソッドが呼び出されると、コントロールは更新処理が完了した状態に設定され、コントロールの描画処理を再描画します。
通常の状態ではComboBoxのItems.Addメソッドが呼び出され、項目が一つ追加されるたびに再描画処理が発生するため、処理に時間がかかりますが、 BeginUpdateメソッドを呼び出しておくことで、Items.Addメソッドが呼び出された際に再描画処理が動作しないようにできるため、処理が高速になります。

実行結果

プロジェクトを実行します。下図のウィンドウが表示されます。
ComboBox のリストに多くの要素を追加すると処理に時間がかかる:画像6

[button2]をクリックします。処理が完了すると処理に要した時間が表示されます。636ミリ秒で処理が完了していることがわかります。 先ほどの単純な項目の追加コードと比較すると4倍程度高速に処理できていることがわかります。
ComboBox のリストに多くの要素を追加すると処理に時間がかかる:画像7

コンボボックスのドロップダウンリストも30,000個項目が追加されています。
ComboBox のリストに多くの要素を追加すると処理に時間がかかる:画像8

コンボボックスのドロップダウンリストに多くの項目を高速に追加することができました。


AuthorPortraitAlt
著者
iPentecのメインプログラマー
C#, ASP.NET の開発がメイン、少し前まではDelphiを愛用
作成日: 2020-06-08
Copyright © 1995–2025 iPentec all rights reserverd.