将数据加载到组合框中的速度很慢

时间:2009-08-04 23:01:09

标签: performance vb6 combobox

我有一个带搜索屏幕的VB6应用程序。在搜索中,我有9个组合框。有些组合框只有几个项目,但有些只有几百项。填充数据需要很长时间(几秒钟)。

每个组合框的配置相同:Sorted = False,Style = 2 - Dropdown List

3个组合框少于20个项目。 1有130件商品。 4有大约250个项目 1有近700项。

我用类似的代码填充所有九个组合框。

While Not RS.EOF

    cmbX.List(i) = RS("Description")
    cmbX.ItemData(i) = RS("Id")

    i = i + 1

    RS.MoveNext
Wend

我尝试设置Visible = False,但它对性能没有影响。

是否有另一种方法来填充比现有方法效果更好的组合框?

7 个答案:

答案 0 :(得分:8)

这是你可以尝试的东西。根据{{​​3}},您可以使用Windows API函数填充组合框,而不是通常的AddItem方法,从而节省大约60%的开销:

Private Const CB_ERR As Long = -1
Private Const CB_ADDSTRING As Long = &H143
Private Const CB_RESETCONTENT As Long = &H14B
Private Const CB_SETITEMDATA As Long = &H151

Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal _
hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long

Public Sub AddItem(cmb As ComboBox, Text As Variant, Optional ItemData As Long)

   Dim l As Long
   Dim s As String

   If VarType(Text) = vbString Then
      s = Text
   Else
      s = Trim$(Str$(Text))
   End If

   l = SendMessage(cmb.hwnd, CB_ADDSTRING, 0&, ByVal s)
   If l <> CB_ERR Then
      SendMessage cmb.hwnd, CB_SETITEMDATA, l, ByVal ItemData
   End If

End Sub

Public Sub Clear(cmb As ComboBox)
   SendMessage cmb.hwnd, CB_RESETCONTENT, 0, 0&
End Sub

你可以通过省略函数调用,直接调用API函数来减少一些。

答案 1 :(得分:3)

你真的需要重新考虑你的设计。没有用户想要在组合框中选择700项。如果你不纠正它,它会让你的应用看起来很混乱。

当我听到这样的情况时,我总会想到一张照片:

答案 2 :(得分:2)

一些建议:

  • 使用With RS

  • 使用Recordset对象的RecordCount属性,而不是在每次迭代时测试EOF(如果RecordCount = -1,那么您应该更改游标类型,光标位置等以确保{支持{1}}。

  • 使用RecordCount循环而不是维护自己的迭代器变量。

  • 使用爆炸操作员(For..Next)。

例如:

!

或许需要考虑的其他事情是将组合的With RS Debug.Assert .RecordCount >= 0 Dim counter As Long For counter = 0 To .RecordCount - 1 cmbX.List(counter) = !Description cmbX.ItemData(counter) = !Id .MoveNext Next End With 属性设置为Sorted,如果需要排序,则使用Recordset的False属性或在源处进行排序(例如,使用SQL代码中的Sort子句。

答案 3 :(得分:2)

您可以尝试告诉组合框在添加新项目时不要重新绘制自己。您可以使用WM_SETREDRAW执行此操作。编辑 - 显然这没有帮助,可能是因为组合框在被填充时被隐藏,这可能会给你带来所有相同的好处。

  Private Declare Function SendMessage Lib "user32" Alias "SendMessageA"( _
    ByVal hwnd As Long, ByVal wMsg As Long, _
    ByVal wParam As Long, lParam As Any) As Long
  Private Const WM_SETREDRAW = &HB

  Call SendMessage(cmbX.hWnd, WM_SETREDRAW, 0, 0&)
  'DO STUFF'
  Call SendMessage(cmbX.hwnd, WM_SETREDRAW, 1, 0&)

警告:许多其他优秀的VB6网站tell代替使用LockWindowUpdate。不要这样做,否则你会get bugs。也是Raymond Chen的不满!

答案 4 :(得分:1)

为什么要预先填充列表然后重新填充List(i)和ItemData(i)?相反,你应该做以下

While Not RS.EOF

    cmbX.AddItem RS("Description")
    cmbX.ItemData(cmbX.NewIndex) = RS("Id")

    RS.MoveNext
Wend

您将看到Robert Harvey的答案与上述代码之间没有任何性能差异。为了提高速度,请使用MarkJ的答案。

另一个问题可能是您用来从数据库中恢复数据的光标。由于您从记录集加载每个项目,因此没有理由拥有服务器端游标。因此,您可能希望在检索记录集时指定客户端游标。

答案 5 :(得分:0)

这似乎很长一段时间。你是如何打开记录集的?您使用的是firehose(只读,仅向前记录集)游标吗?如果不是,那么可能会从中获得一些性能提升。确保您的SQL语句仅返回组合框所需的数据(即不要使用SELECT *)。

如果您的SQL语句包含WHERE子句或JOINS,请确保在相应的字段上有索引。

如果您使用ACCESS作为后端,则可以通过升级到SQL Server Express立即提高速度。

答案 6 :(得分:0)

''填充COMBOBOX

我必须等待20秒才能在我的程序中填充80,000条记录的城市组合框 我尝试了几种方法,但所有这些方法都更糟糕

这是我的原始代码

    Me.txt_City.DataSource = tblCities
    Me.txt_City.ValueMember = "city"
    Me.txt_City.DisplayMember = "city"

并猜测是什么,我只是将第一行代码移到了最后 然后人口只用了5秒钟

    Me.txt_City.ValueMember = "city"
    Me.txt_City.DisplayMember = "city"

    Me.txt_City.DataSource = tblCities

试试吧