Форум программистов, компьютерный форум, киберфорум
Delphi для начинающих
Войти
Регистрация
Восстановить пароль
 
 
Рейтинг 4.80/5: Рейтинг темы: голосов - 5, средняя оценка - 4.80
1 / 1 / 1
Регистрация: 06.05.2017
Сообщений: 60
1

Долгая фильтрация стринггрида в потоке

14.07.2017, 09:34. Показов 968. Ответов 20
Метки нет (Все метки)

Почему в потоке фильтрация таблицы типа stringgrid происходит раз в 10 дольше чем не в потоке???
Приоритет потока пробовал ставить на tphigher - ничего не изменилось

Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
var sg1list : tstringlist;  // глобальная переменная, содержит в себе ~10000 строк таблицы
 
procedure TForm1.Button1Click(Sender: TObject);   // создание потока
begin
  testthread := ttestthread.Create(false);
  testthread.FreeOnTerminate:=true;
  testthread.Priority:=tpNormal;
end;
 
procedure ttestthread.execute;            // реализация фильтрации
var
  i, n : integer;  
begin  
  n := 0;
  for i := 0 to sg1list.Count-1 do
    if pos(form1.edit1.Text,sg1list[i]) > 0 then
    begin    
      form1.sg1.Rows[n].DelimitedText := sg1list[i];
      inc(n);
      form1.sg1.RowCount := n;
    end;
end;
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
14.07.2017, 09:34
Ответы с готовыми решениями:

сохранить из стринггрида
подскажите пожалуста алгоритм написания сохранения значений ячеек stringgrid-а размерностью Іх2 (не...

Из стринггрида сохранить в файл
var f:textfile; i,j:integer; begin if SaveDialog1.Execute then begin...

Запись из стринггрида в файл
var i,j:integer; b:string; begin b:=''; if dlgSave1.Execute then AssignFile(fFile,...

Простейшая сортировка стринггрида
Есть форма на которой есть стринггрид и кнопка. Стринггрид состоит и одного столбца. Нужно сделать...

__________________
20
421 / 339 / 196
Регистрация: 20.10.2016
Сообщений: 1,078
14.07.2017, 09:46 2
Зачем 10000 раз в потоке обращаться к GUI (form1.edit1.Text)?
Где выход из цикла? нашли совпадение в первой строке и дальше лопатим 10000 строк?
Лучше по окончании работы потока в OnTerminate выводить результат в грид.
0
3579 / 3050 / 821
Регистрация: 29.08.2013
Сообщений: 20,356
Записей в блоге: 2
14.07.2017, 09:51 3
и зачем в потоке вообще обращаться к гриду?
передай потоку массив - пусть сортирует, а на выходе уже сортированный массив записывай в грид
0
1 / 1 / 1
Регистрация: 06.05.2017
Сообщений: 60
14.07.2017, 09:55  [ТС] 4
TFullControl,
1) а как к нему можно обратиться единожды?
2) зачем выходить из цикла, если совпадающих значений может быть больше одного
3) как это сделать и повлияет ли это на производительность?

Добавлено через 2 минуты
qwertehok, ааа, по поводу первого пункта понял (занести в переменную, да?)...
по остальным пунктам жду вашего ответа
0
421 / 339 / 196
Регистрация: 20.10.2016
Сообщений: 1,078
14.07.2017, 09:58 5
1. Считать в переменную и обращаться к ней. Передавать в поток не грид и этит, а переменную и массив значений из грида.
2. Может, невнимательно ваш код прочел, тут я был не прав.
3. Уже ответил, в OnTerminate выводить результат в грид, в потоке к GUI вообще обращаться не стоит.
0
1 / 1 / 1
Регистрация: 06.05.2017
Сообщений: 60
14.07.2017, 10:05  [ТС] 6
TFullControl, еще такой момент, я вроде как к гриду и не обращаюсь, у меня sg1list : tstringlist - глобальная переменная со списком строк таблицы.
В остальном спасибо, сейчас буду пробовать... вообще у меня несколько потоков и в каждом я по незнанию обращаюсь к gui
щас придется все перелопачивать
0
Житель Земли
2838 / 2709 / 375
Регистрация: 26.07.2011
Сообщений: 10,769
Записей в блоге: 1
14.07.2017, 10:18 7
Цитата Сообщение от qad_quolo Посмотреть сообщение
testthread := ttestthread.Create(false);
а еще в скобках долно быть true (CreateSuspended - Создать приостановленным), если после создания ты собираешься настраивать параметры потока либо передавать в него данные. после всех манипуляций вызываешь testthread.start (либо testthread.resume, если Делфи старая)
0
421 / 339 / 196
Регистрация: 20.10.2016
Сообщений: 1,078
14.07.2017, 10:26 8
Цитата Сообщение от qad_quolo Посмотреть сообщение
я вроде как к гриду и не обращаюсь
А это что?
Цитата Сообщение от qad_quolo Посмотреть сообщение
form1.sg1.RowCount := n;
0
1 / 1 / 1
Регистрация: 06.05.2017
Сообщений: 60
14.07.2017, 17:30  [ТС] 9
Я так понял проблема долгой фильтрации заключалась только в этой строчке
form1.sg1.RowCount := n;

И возможно в этой
if pos(form1.edit1.Text,sg1list[i]) > 0 then

Теперь фильтрует быстро, но появилась еще одна проблема. Почему-то некоторые ячейки становятся пустыми после фильтрации (причем в случайном порядке), хотя в моем tstringlist эти значения имеются (вывожу строчку в мемо для проверки).
То есть, например, строка в tstringlist "машина;команда;казус;;;" при фильтрации по букве "а" может отобразиться в таблице как "машина/пустая ячейка/казус/пустая ячейка/пустая ячейка/пустая ячейка". В итоге слово команда, по какой-то причине не появилось в ячейке. Причем при повторной фильтрации может отобразиться КОРРЕКТНО.

Добавлено через 20 минут
Правда я вывожу результат не в OnTerminate, это очень важно??
0
2106 / 1252 / 444
Регистрация: 29.05.2013
Сообщений: 5,634
14.07.2017, 18:22 10
Значит выводите без синхронизации с основным приложением (Synchronize), что и приводит к потере данных, это у вас еще относительно доброе поведение, могло быть намного хуже.
0
1 / 1 / 1
Регистрация: 06.05.2017
Сообщений: 60
14.07.2017, 20:52  [ТС] 11
Подскажите, пожалуйста, правильно я сделал synchronize и объявил локальные переменные в классе потока или что-то нужно изменить. В таком виде вроде работает без ошибок.

Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
  Tfilterthread = class(tthread)
  private
       { Private declarations }
     sg2list : tstringlist;              // список отфильтрованных данных
     z : boolean;            // определитель наличия фильтрованных данных
     edit : string;
     procedure sg1filtering;
  protected
     procedure execute; override;
  end;
 
var
  sg1list : tstringlist;       // глобальный список изначально имеющихся данных в таблице
 
implementation
 
{$R *.dfm}
 
procedure TForm1.Edit5Change(Sender: TObject);    // создание потока
begin
  filterthread := tfilterthread.Create(false);
  filterthread.FreeOnTerminate:=true;
  filterthread.Priority:=tpNormal;
 end;
 
procedure Tfilterthread.execute;              // Фильтрация таблицы
var
  i  : integer;
begin
  z := false;
  edit := form1.edit5.text;
  sg2list := tstringlist.Create;
 
  if edit <> '' then
  begin
    for i := 0 to sg1list.Count-1 do
      if pos(edit,sg1list[i]) > 0 then
      begin
        z := true;                    // нашли совпадение
        sg2list.Add(sg1list[i]);        // добавили в список
      end;
  end;
  Synchronize(sg1filtering);
end;
 
procedure Tfilterthread.sg1filtering;
var
  i : integer;
begin
  form1.sg1.rowcount := sg2list.Count;
  for i := 0 to sg2list.count-1 do
    form1.sg1.rows[i].DelimitedText := sg2list[i];   // записываем отфильтрованные данные в таблицу, если они есть
 
 
  if z = false then  begin clearsg(form1.sg1); form1.sg1.RowCount := 1; end;  // если совпадений не найдено, таблица пустая
 
  if edit = '' then                      // если значение в edit пустое, заполнить таблицу изначальными данными
  begin
    clearsg(form1.sg1);
    form1.sg1.RowCount := sg1list.Count;
    for i := 0 to sg1list.Count-1 do
      form1.sg1.Rows[i].DelimitedText := sg1list[i];
  end;
  freeandnil(sg2list);
 end;
0
3579 / 3050 / 821
Регистрация: 29.08.2013
Сообщений: 20,356
Записей в блоге: 2
15.07.2017, 00:25 12
Цитата Сообщение от qad_quolo Посмотреть сообщение
edit := form1.edit5.text;
при создании потока заполняй переменные
0
1 / 1 / 1
Регистрация: 06.05.2017
Сообщений: 60
15.07.2017, 04:38  [ТС] 13
qwertehok, и я все равно не понимаю, почему без синхронизации при заполнении таблицы могут не прописываться значения в ячейках при событии edit.onchange. Ведь к таблице больше не было обращений со стороны других потоков, я просто вводил один символ в edit и некоторые ячейки оказывались пустыми
0
421 / 339 / 196
Регистрация: 20.10.2016
Сообщений: 1,078
15.07.2017, 09:44 14
Цитата Сообщение от qad_quolo Посмотреть сообщение
Ведь к таблице больше не было обращений со стороны других потоков
Основной поток постоянно обрабатывает GUI.
А то как и где вы создаете поток это вообще бред, вот подумайте, в Edit5Change каждый раз при вводе создается поток, причем каждый новый поток вы тычете в одну и туже переменную, теряя при этом ссылки на ранее созданные.
Вот вам ситуация, вы вводите в поиске слово "белиберда", после каждого нажатия кнопки создается поток, и с большой долей вероятности предыдущий поток не завершит работу до того как будет создан новый.
Тут логичней либо запускать поиск по кнопке, либо ввести в поток флаг, позволяющий ему работать. И при создании нового потока, проверять, а существует ли еще предыдущий поток и если существует то опускать флаг и тем самым завершать работу предыдущего, с последующим запуском нового.
0
1 / 1 / 1
Регистрация: 06.05.2017
Сообщений: 60
15.07.2017, 10:25  [ТС] 15
Цитата Сообщение от TFullControl Посмотреть сообщение
вы вводите в поиске слово "белиберда"
Цитата Сообщение от qad_quolo Посмотреть сообщение
я просто вводил один символ в edit и некоторые ячейки оказывались пустыми
даже при вводе одного символа некоторые ячейки остаются пустыми
+ в конце потока я вывожу в мемо сообщение о том, что процедура фильтрации завершена... то есть я не мог "затирать" предыдущую переменную
0
2106 / 1252 / 444
Регистрация: 29.05.2013
Сообщений: 5,634
15.07.2017, 15:10 16
Поиск значения на вводе делают несколько иначе.
Устанавливают некую минимальную паузу между нажатиями клавиш, например 2 секунды. Т.е. если пользователь не нажал в этот промежуток на клавиатуре никакой клавиши, то тогда запускается поисковый запрос введенного значения. Если же после запуска поискового запроса пользователь снова продолжает набор текста, то поиск прерывается.
Такой подход позволяет более грамотно осуществлять поиск, т.к. пользователь может ошибиться при вводе и начнет править строку, а вы ринулись искать нафик ему не нужную информацию.
0
1 / 1 / 1
Регистрация: 06.05.2017
Сообщений: 60
16.07.2017, 15:01  [ТС] 17
Пытливый, я тоже сначала думал так сделать, возможно, и сделаю паузу с ожиданием ввода на 250-300 мсек, но это уже мелочи...
В общем, фильтрацию решил не делать в потоке, т.к. понял что в этом нет смылса, раз уж изменять визуальные объекты из потока не рекомендуется, а синхронизация по сути и есть тот самый основной поток...
Буду использовать потоки только в тех случаях, где нужно делать различного рода паузы.

Добавлено через 21 час 51 минуту
И еще 1 вопрос разъясните плз... пытался гуглить, но везде пишут только про изменение объектов vcl, а не про считывание данных из них
я понял, что из execute потока нельзя обращаться к визуальным объектам с целью их изменения/модификации, но можно ли к ним обращаться для получения данных? Например, для получения значения ячейки из того же стринггрида (a := form1.sg1.cells[i,n])
0
2106 / 1252 / 444
Регистрация: 29.05.2013
Сообщений: 5,634
16.07.2017, 19:50 18
Вы неправильно поняли. Можно обращаться к vcl, но делать надо это правильно. Что находится под капотом конкретного компонента vcl знает только разработчик этого компонента и вполне может случится, что на ваш взгляд безобидное чтение приведет к исключительной ситуации, поэтому не стоит надеяться на удачу, а просто поместите обращение к компоненту в Synchronize.
0
1 / 1 / 1
Регистрация: 06.05.2017
Сообщений: 60
17.07.2017, 00:07  [ТС] 19
Пытливый, спасибо, буду стараться так и делать!
0
Massaraksh7
17.07.2017, 07:09     Долгая фильтрация стринггрида в потоке
  #20

Не по теме:

Цитата Сообщение от Пытливый Посмотреть сообщение
Что находится под капотом конкретного компонента vcl знает только разработчик этого компонента
Или тот, кто не поленился полазить по каталогу Sources.

0
17.07.2017, 07:09
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
17.07.2017, 07:09
Привет! Вот еще темы с ответами:

Картинки в ячейках стринггрида
Суть в том, что по нажатию на ячейку, туда должна загружаться определенная картинка. Вот что у меня...

Сортировка из стринггрида по возрастанию
Суть такова, есть числа (уже заданные в таблице) нужно из отсортировать и вывести в тмемо в порядке...

Удалить несколько столбцов из стринггрида
Есть stringgrid в котором 22 столбца, из этих 22 столбцов нужно удалить все кроме второго и пятого,...

Расчет среднего арифметического из стринггрида
Привет! Есть стринггрид из ста строк. Нужно посчитать среднее арифметическое по 20 строкам (в...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2021, vBulletin Solutions, Inc.