VB6 コンボボックスのBeginUpdateにかわるものは?
投稿者 魔界の仮面弁士  (社会人)
投稿日時
2022/5/11 19:24:43
手元に VB6 が残ってないので試せないので、以下すべて未検証ですが。
そもそも 10000 件のデータを ComboBox に追加する時点で、
使いにくすぎるかと。選択したり探すのも大変なので、
まずは UI を見直すことをお奨めします。
> とても遅いです。
どのくらいかかるのですか?
> 簡単に書くと下記のようなものなのですが...
ひとまず、Visible = False 状態にしてから Clear & AddItem して、
完了後に Visible = True してみたら高速化されないでしょうか?
あるいは、ComboBox 操作前に
SendMessageA ComboBox1.hWnd, WM_SETREDRAW, ByVal 0&, ByVal 0&
を呼んでから Clear & AddItem して、操作後に
SendMessageA ComboBox1.hWnd, WM_SETREDRAW, ByVal 1&, ByVal 0&
を呼んでみるとか。
それでも遅いなら、たとえば 0.3 秒間で何件ぐらい登録できるのかを見極め、
その件数分、Timer 等を併用して、一度に少しずつ追加するようにするとか。
そもそも 10000 件のデータを ComboBox に追加する時点で、
使いにくすぎるかと。選択したり探すのも大変なので、
まずは UI を見直すことをお奨めします。
> とても遅いです。
どのくらいかかるのですか?
> 簡単に書くと下記のようなものなのですが...
ひとまず、Visible = False 状態にしてから Clear & AddItem して、
完了後に Visible = True してみたら高速化されないでしょうか?
あるいは、ComboBox 操作前に
SendMessageA ComboBox1.hWnd, WM_SETREDRAW, ByVal 0&, ByVal 0&
を呼んでから Clear & AddItem して、操作後に
SendMessageA ComboBox1.hWnd, WM_SETREDRAW, ByVal 1&, ByVal 0&
を呼んでみるとか。
それでも遅いなら、たとえば 0.3 秒間で何件ぐらい登録できるのかを見極め、
その件数分、Timer 等を併用して、一度に少しずつ追加するようにするとか。
投稿者 魔界の仮面弁士  (社会人)
投稿日時
2022/5/11 20:00:23
あとは、「標準コントロール」では「ActiveXコントロール」に切り替えて、
ADOData Control(ADODC1) → DataCombo コントロール
Data Control(Data1) → DBCombo コントロール
で、大量データをバインドした時の時間と比較してみるとか。(環境が無いので未確認)
ADOData Control(ADODC1) → DataCombo コントロール
Data Control(Data1) → DBCombo コントロール
で、大量データをバインドした時の時間と比較してみるとか。(環境が無いので未確認)
DataCombo Control (OLEDB) … msdatlst.ocx
DataList Control (OLEDB) … msdatlst.ocx
DBCombo Control … dblist32.ocx
DBList Control … dblist32.ocx
DataList Control (OLEDB) … msdatlst.ocx
DBCombo Control … dblist32.ocx
DBList Control … dblist32.ocx
投稿者 はなな  (社会人)
投稿日時
2022/5/12 09:49:28
魔界の仮面弁士様、ありがとうございます。
>そもそも 10000 件のデータを ComboBox に追加する時点で、
10000 件は例えで書いてしまいました。すみません。
実際は各マスタ(多いものは300件程)を読み込んでFORM_LOAD時に表示させています。
コンボボックスの数は13個です。
各マスタを読み込みコンボボックスに表示させる、までの時間はだいたいい0.76秒です。
私のところでは0.76秒ですが、運用環境ではもっと遅いようです。
>ひとまず、Visible = False 状態にしてから Clear & AddItem して、
>完了後に Visible = True してみたら高速化されないでしょうか?
こちらを試してみましたが、0.76秒で変わりませんでした。
>あるいは、ComboBox 操作前に
> SendMessageA ComboBox1.hWnd, WM_SETREDRAW, ByVal 0&, ByVal 0&
>を呼んでから Clear & AddItem して、操作後に
> SendMessageA ComboBox1.hWnd, WM_SETREDRAW, ByVal 1&, ByVal 0&
>を呼んでみるとか。
こちらを試しているところですが、私の知識不足によりエラーでまだ実行できておりません。
また報告させていただきますので、よろしくお願い致します。
>そもそも 10000 件のデータを ComboBox に追加する時点で、
10000 件は例えで書いてしまいました。すみません。
実際は各マスタ(多いものは300件程)を読み込んでFORM_LOAD時に表示させています。
コンボボックスの数は13個です。
各マスタを読み込みコンボボックスに表示させる、までの時間はだいたいい0.76秒です。
私のところでは0.76秒ですが、運用環境ではもっと遅いようです。
>ひとまず、Visible = False 状態にしてから Clear & AddItem して、
>完了後に Visible = True してみたら高速化されないでしょうか?
こちらを試してみましたが、0.76秒で変わりませんでした。
>あるいは、ComboBox 操作前に
> SendMessageA ComboBox1.hWnd, WM_SETREDRAW, ByVal 0&, ByVal 0&
>を呼んでから Clear & AddItem して、操作後に
> SendMessageA ComboBox1.hWnd, WM_SETREDRAW, ByVal 1&, ByVal 0&
>を呼んでみるとか。
こちらを試しているところですが、私の知識不足によりエラーでまだ実行できておりません。
また報告させていただきますので、よろしくお願い致します。
投稿者 魔界の仮面弁士  (社会人)
投稿日時
2022/5/12 11:37:34
.NET の BeingUpdate / EndUpdate は、WM_SETREDRAW を呼び出していますので、先の案はそれを模したものです。
https://dobon.net/vb/dotnet/control/beginupdate.html#wmsetredraw
> 私の知識不足によりエラーでまだ実行できておりません。
手元に環境が無いので掲示板直書きですが、宣言はこんな感じ。
> 0.76秒で変わりませんでした。
Form_Load で処理しているなら変わらないと思います。
通常は Load イベントを抜けるまで、コントロールは表示されていない状態ですから。
> コンボボックスの数は13個です。
トータルで 0.76 秒なのか、それとも、13 個 × 0.76 秒≒ 10秒程度なのかはさておき。
質問内容からすると、.NET で BeginUpdate した時には 0.76 秒を下回るので、
VB6 でもそれを目指したい…ということでしょうか?
ちなみに当方の .NET で試した時には、13個×300件で 1.2 秒程度でした(AddRange でも同様)。
BeginUpdate しない場合は 3.3 秒程度でした。
> 各マスタを読み込みコンボボックスに表示させる、までの時間はだいたいい0.76秒です。
> 私のところでは0.76秒ですが、運用環境ではもっと遅いようです。
運用環境のボトルネックは ComboBox だけでしょうか。
検証用に、マスターではなく最初の例のような固定的なデータを 300件用意し、
それを単純に追加するだけの処理でも、同じように時間がかかるか確認してみてください。
たとえばデータベースアクセスがある場合における当方の経験ですが、
対 Oracle の場合において、oo4o でのダイナセットと ADODB の前方カーソルを
比較したところ、MoveNext の時間は ADODB の方が早かったため、
ミドルウェアの変更で高速化させたことがあります。
https://dobon.net/vb/dotnet/control/beginupdate.html#wmsetredraw
> 私の知識不足によりエラーでまだ実行できておりません。
手元に環境が無いので掲示板直書きですが、宣言はこんな感じ。
Private Const WM_SETREDRAW As Integer = &HB
Private Declare Function SendMessageA Lib "user32" (ByVal hwnd As OLE_HANDLE, ByVal msg As Long, wParam As Any, lParam As Any) As Long
> 0.76秒で変わりませんでした。
Form_Load で処理しているなら変わらないと思います。
通常は Load イベントを抜けるまで、コントロールは表示されていない状態ですから。
> コンボボックスの数は13個です。
トータルで 0.76 秒なのか、それとも、13 個 × 0.76 秒≒ 10秒程度なのかはさておき。
質問内容からすると、.NET で BeginUpdate した時には 0.76 秒を下回るので、
VB6 でもそれを目指したい…ということでしょうか?
ちなみに当方の .NET で試した時には、13個×300件で 1.2 秒程度でした(AddRange でも同様)。
BeginUpdate しない場合は 3.3 秒程度でした。
Public Class Form1
Private combos As New List(Of ComboBox)()
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
For i = 1 To 13
Dim c As New ComboBox() With {.Name = $"ComboBox{i}", .DropDownStyle = ComboBoxStyle.DropDownList}
c.Items.Add(c.Name)
c.SelectedIndex = 0
combos.Add(c)
FlowLayoutPanel1.Controls.Add(c)
Next
End Sub
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim sw = Stopwatch.StartNew()
For Each cb As ComboBox In combos
cb.BeginUpdate()
cb.Items.Clear()
For n = 1 To 300
cb.Items.Add(n)
Next
cb.EndUpdate()
Next
sw.Stop()
Button1.Text = sw.Elapsed.ToString()
End Sub
End Class
> 各マスタを読み込みコンボボックスに表示させる、までの時間はだいたいい0.76秒です。
> 私のところでは0.76秒ですが、運用環境ではもっと遅いようです。
運用環境のボトルネックは ComboBox だけでしょうか。
検証用に、マスターではなく最初の例のような固定的なデータを 300件用意し、
それを単純に追加するだけの処理でも、同じように時間がかかるか確認してみてください。
たとえばデータベースアクセスがある場合における当方の経験ですが、
対 Oracle の場合において、oo4o でのダイナセットと ADODB の前方カーソルを
比較したところ、MoveNext の時間は ADODB の方が早かったため、
ミドルウェアの変更で高速化させたことがあります。
投稿者 はなな  (社会人)
投稿日時
2022/5/12 12:18:46
魔界の仮面弁士様、ありがとうございます。
結果から申しますと、0.76秒から0.36秒に短縮することが出来ました!
>.NET の BeingUpdate / EndUpdate は、WM_SETREDRAW を呼び出していますので、先の案はそれを模したものです。
実はこちらを見ていたのですが、宣言の記載がうまくいかずに苦戦していました。
魔界の仮面弁士様に宣言のところを記載いただいたおかげで、実行することが出来ました。
ありがとうございました。
>トータルで 0.76 秒なのか、それとも、13 個 × 0.76 秒≒ 10秒程度なのかはさておき。
トータルで 0.76 秒でした。
>質問内容からすると、.NET で BeginUpdate した時には 0.76 秒を下回るので、
>VB6 でもそれを目指したい…ということでしょうか?
はい、その通りです。
>運用環境のボトルネックは ComboBox だけでしょうか。
>検証用に、マスターではなく最初の例のような固定的なデータを 300件用意し、
>それを単純に追加するだけの処理でも、同じように時間がかかるか確認してみてください。
データアクセスが遅い原因かと思って調査したのですが、
単純に追加するだけの処理でも同じくらいの時間がかかっていましたので
コンボボックスに表示するところで時間がかかっていると分かり、今回の質問をさせていただきました。
おかげさまで、時間短縮することができ助かりました。
ありがとうございました。
結果から申しますと、0.76秒から0.36秒に短縮することが出来ました!
>.NET の BeingUpdate / EndUpdate は、WM_SETREDRAW を呼び出していますので、先の案はそれを模したものです。
実はこちらを見ていたのですが、宣言の記載がうまくいかずに苦戦していました。
魔界の仮面弁士様に宣言のところを記載いただいたおかげで、実行することが出来ました。
ありがとうございました。
>トータルで 0.76 秒なのか、それとも、13 個 × 0.76 秒≒ 10秒程度なのかはさておき。
トータルで 0.76 秒でした。
>質問内容からすると、.NET で BeginUpdate した時には 0.76 秒を下回るので、
>VB6 でもそれを目指したい…ということでしょうか?
はい、その通りです。
>運用環境のボトルネックは ComboBox だけでしょうか。
>検証用に、マスターではなく最初の例のような固定的なデータを 300件用意し、
>それを単純に追加するだけの処理でも、同じように時間がかかるか確認してみてください。
データアクセスが遅い原因かと思って調査したのですが、
単純に追加するだけの処理でも同じくらいの時間がかかっていましたので
コンボボックスに表示するところで時間がかかっていると分かり、今回の質問をさせていただきました。
おかげさまで、時間短縮することができ助かりました。
ありがとうございました。
投稿者 魔界の仮面弁士  (社会人)
投稿日時
2022/5/13 19:33:44
> 宣言はこんな感じ。
> Private Const WM_SETREDRAW As Integer = &HB
ごめんなさい、間違えていました。
本来はこうですね。
Private Const WM_SETREDRAW As Long = &HB&
※ SendMessage 側で ByVal msg As Long にて受けるようにしているので、実害は無いですが。
> Private Const WM_SETREDRAW As Integer = &HB
ごめんなさい、間違えていました。
本来はこうですね。
Private Const WM_SETREDRAW As Long = &HB&
※ SendMessage 側で ByVal msg As Long にて受けるようにしているので、実害は無いですが。
投稿者 はなな  (社会人)
投稿日時
2022/5/16 09:46:48
魔界の仮面弁士さん、ありがとうござます。
IntegerでなくLongですね!
実害は無い、とのことですが修正しておきます。
ありがとうございました。
IntegerでなくLongですね!
実害は無い、とのことですが修正しておきます。
ありがとうございました。
データの数も多いですが、表示するコンボボックスも複数あります。
簡単に書くと下記のようなものなのですが...
Dim Count as Long
Dim i as Long
Count = 10000
cmbbox1.clear
cmbbox2.clear
cmbbox3.clear
cmbbox4.clear
cmbbox5.clear
For i = 0 To Count - 1
cmbbox1.AddItem i
cmbbox2.AddItem i+10
cmbbox3.AddItem i+100
cmbbox4.AddItem i+1000
cmbbox5.AddItem i+10000
Next
VB.NETのBeginUpdate、EndUpdateの代わりとなるようなものはないのでしょうか?
どなたかご存じの方がいましたら教えて下さい。
よろしくお願い致します。