ComboBox のリストに多くの要素を追加すると処理に時間がかかる現象の対処法を紹介します。
ComboBoxのドロップダウンリストに多くの項目を単純に追加すると処理に時間がかります。
ドロップダウンリストに多くの項目を追加する場合は、BeginUpdate()
メソッドを利用します。
単純な実装でどの程度の時間がかかるか確認します。以下のプログラムを作成します。
下図のフォームを作成します。Combobox, Button, 複数行のTextBoxを配置します。
下記のコードを記述します。
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());
}
プロジェクトを実行します。下図のウィンドウが表示されます。
[button1]をクリックします。コンボボックスに項目が追加されます。追加処理が完了すると、処理に要した時間がテキストボックスに表示されます。
今回の処理は2,869ミリ秒(=2.8秒)かかっていることがわかります。
コンボボックスのドロップダウンリストを確認すると、30,000個アイテムが追加されていることが確認できます。
BeginUpdate, EndUpdate メソッドを利用してコンボボックスへの項目の追加を高速に処理します。
下図のフォームを作成します。Combobox, Buttonを2つ, 複数行のTextBoxを配置します。
下記のコードを記述します。
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
メソッドが呼び出されると、コントロールは更新処理が完了した状態に設定され、コントロールの描画処理を再描画します。
通常の状態ではComboBoxのItems.Add
メソッドが呼び出され、項目が一つ追加されるたびに再描画処理が発生するため、処理に時間がかかりますが、
BeginUpdate
メソッドを呼び出しておくことで、Items.Add
メソッドが呼び出された際に再描画処理が動作しないようにできるため、処理が高速になります。
プロジェクトを実行します。下図のウィンドウが表示されます。
[button2]をクリックします。処理が完了すると処理に要した時間が表示されます。636ミリ秒で処理が完了していることがわかります。
先ほどの単純な項目の追加コードと比較すると4倍程度高速に処理できていることがわかります。
コンボボックスのドロップダウンリストも30,000個項目が追加されています。
コンボボックスのドロップダウンリストに多くの項目を高速に追加することができました。