Медленная загрузка данных в поле со списком - PullRequest
3 голосов
/ 05 августа 2009

У меня есть приложение VB6 с экраном поиска. На поиске у меня 9 комбо-боксов. Некоторые комбо-боксы содержат только пару предметов, а некоторые - пару сотен предметов. Заполнение данных занимает много времени (пара секунд).

Все поля со списком настроены одинаково: Sorted = False, Style = 2 - Раскрывающийся список

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 ]

8 голосов
/ 05 августа 2009

Вот что вы можете попробовать. Согласно этой записи вы можете сократить свои накладные расходы на 60%, используя функцию Windows API для заполнения поля со списком вместо обычного метода AddItem:

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 напрямую.

3 голосов
/ 05 августа 2009

Вам действительно нужно переосмыслить свой дизайн. Ни один пользователь не захочет выбирать между 700 элементами в комбинированном окне. Это сделает ваше приложение загроможденным, если вы его не исправите.

Картина всегда приходит мне в голову, когда я слышу такую ​​ситуацию:

image

2 голосов
/ 05 августа 2009

Вы можете указать комбобоксу не перекрашивать себя, пока добавляете новые элементы. Вы можете сделать это с помощью 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 говорят , что вам следует использовать LockWindowUpdate . Не делайте этого, иначе вы получите ошибок . Также оплошность Раймонд Чен !

2 голосов
/ 05 августа 2009

Некоторые предложения:

  • Использование With RS.

  • Используйте свойство RecordCount объекта Recordset вместо проверки на EOF на каждой итерации (если RecordCount = -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 комбо значение False, и если требуется сортировка, либо используйте свойство Sort набора записей, либо выполните сортировку в источнике (например, с помощью предложения ORDER BY в SQL код).

1 голос
/ 05 августа 2009

Почему вы предварительно заполняете список, а затем снова заполняете List (i) и ItemData (i)? Вместо этого вы должны сделать следующее

While Not RS.EOF

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

    RS.MoveNext
Wend

Вы увидите нулевую разницу в производительности между ответом Роберта Харви и приведенным выше кодом. Для дополнительной скорости примените ответ MarkJ.

Еще одной проблемой может быть курсор, который вы используете для возврата данных из базы данных. Поскольку вы загружаете каждый элемент из набора записей, есть очень мало причин иметь серверный курсор. Поэтому вы можете указать курсор на стороне клиента при получении набора записей.

0 голосов
/ 01 октября 2014

'' Заполнить 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

попробуйте

0 голосов
/ 05 августа 2009

Это похоже на долгое время. Как вы открываете свои наборы записей? Используете ли вы курсоры firehose (только для чтения, только для записи вперед)? Если нет, вы можете получить некоторое улучшение производительности от этого. Убедитесь, что ваши операторы SQL ТОЛЬКО возвращают данные, которые им нужны для полей со списком (т.е. НЕ используйте SELECT *).

Если ваши операторы SQL содержат предложения WHERE или JOINS, убедитесь, что у вас есть индексы в соответствующих полях.

Если вы используете ACCESS в качестве бэкэнда, вы сразу же получите повышение скорости за счет перехода на SQL Server Express.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...