Модераторы: Poseidon, Snowy, bems, MetalFan

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> TThread и TStringGrid 
:(
    Опции темы
Ablis
Дата 14.8.2013, 13:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 11
Регистрация: 13.4.2011

Репутация: нет
Всего: нет



Всем доброго времени суток. Столкнулся с непонятной для себя проблемой.

В программе использую следующий поток:

Код

type
 TProcessInfo = class(TThread)
  public
    ProcessList: PListStruct;
  protected
    procedure ShowResult;
    procedure Execute; override;
end;


И собственно процедуры в потоке:

Код

procedure TProcessInfo.ShowResult;
var
 row,temp,max,temp1,max1:integer;
begin
  Form1.StringGrid1.RowCount:= ProcessList.ItemCount+1;
  max:= 0;
  max1:= 0;
  for row:= 1 to Form1.StringGrid1.RowCount do
   Form1.StringGrid1.Rows[row].Clear();
  for row:= 1 to Form1.StringGrid1.RowCount do
   with Form1.StringGrid1 do
    begin
      if ProcessList.pData[row-1].ProcessName<>'' then
       begin
         Cells[0, row]:= String(ProcessList.pData[row-1].ProcessName);
         Cells[1, row]:= IntToStr(ProcessList.pData[row-1].ProcessId);
         Cells[2, row]:= BoolToStr(ProcessList.pData[row-1].Visible);

         Cells[4, row]:= ProcessList.pData[row-1].Path;
         temp:= canvas.textWidth(cells[4, row]);
         temp1:= canvas.textWidth(cells[0, row]);
         if temp1>max1 then max1:= temp1;
         if temp>max then max:= temp;
         colWidths[4]:= max + gridLineWidth + 2;
         colWidths[0]:= max1 + gridLineWidth + 2;
       end;
    end;
end;

procedure TProcessInfo.Execute;
var
  AR: AntiRootkitEngine;
  step: integer;
begin
  AR:= AntiRootkitEngine.Create;
  ProcessList.ItemCount:=0;
  SetLength(ProcessList.pData, 0);
  AR.GetFullProcessesInfoOs(ProcessList, step);
  Synchronize(ShowResult);
  AR.Free;
end;


 AntiRootkitEngine - это большой класс по поиску скрытых процессов. Пока все было не в отдельном потоке, все прекрасно выводилось в StringGrid, но стоило код запихнуть в TThread, как после отработки потока, в таблицу выводится только строка на которой стоит фокус, хотя количество строк визуально изменяется, а также перестает работать выравнивание по ширине в столбцах. Под отладкой структура данных ProcessList корректно заполнена.
Если заменить:
Код

procedure TProcessInfo.ShowResult;
var
 row,temp,max,temp1,max1:integer;
begin
  Form1.StringGrid1.RowCount:= ProcessList.ItemCount+1;
  max:= 0;
  max1:= 0;
  for row:= 1 to Form1.StringGrid1.RowCount do
   Form1.StringGrid1.Rows[row].Clear();
  for row:= 1 to Form1.StringGrid1.RowCount do
   {with Form1.StringGrid1 do
    begin
      if ProcessList.pData[row-1].ProcessName<>'' then
       begin
         Cells[0, row]:= String(ProcessList.pData[row-1].ProcessName);
         Cells[1, row]:= IntToStr(ProcessList.pData[row-1].ProcessId);
         Cells[2, row]:= BoolToStr(ProcessList.pData[row-1].Visible);

         Cells[4, row]:= ProcessList.pData[row-1].Path;
         temp:= canvas.textWidth(cells[4, row]);
         temp1:= canvas.textWidth(cells[0, row]);
         if temp1>max1 then max1:= temp1;
         if temp>max then max:= temp;
         colWidths[4]:= max + gridLineWidth + 2;
         colWidths[0]:= max1 + gridLineWidth + 2;
       end;
    end;}
   Form1.Memo1.Lines.Add(String(ProcessList.pData[row-1].ProcessName)); 
end;

То в Memo все прекрасно отображается. Токда почему не выводится в таблицу? smile 
Помогите пожалуйста разобраться! smile 
PM MAIL   Вверх
kami
Дата 14.8.2013, 13:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1806
Регистрация: 25.8.2007
Где: Санкт-Петербург

Репутация: 23
Всего: 72



Цитата(Ablis @  14.8.2013,  13:45 Найти цитируемый пост)
Пока все было не в отдельном потоке, все прекрасно выводилось в StringGrid, но стоило код запихнуть в TThread

Запомните раз и навсегда - нельзя к визуальным компонентам обращаться из дополнительного потока.
Многопоточность - как это делается в Delphi
PM MAIL WWW   Вверх
Ablis
Дата 14.8.2013, 13:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 11
Регистрация: 13.4.2011

Репутация: нет
Всего: нет



Мммм, а Synchronize?
Стаью перечитаю.
PM MAIL   Вверх
northener
Дата 14.8.2013, 13:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1361
Регистрация: 2.9.2010

Репутация: 8
Всего: 20



Цитата(Ablis @  14.8.2013,  13:45 Найти цитируемый пост)
Пока все было не в отдельном потоке, все прекрасно выводилось в StringGrid

И ошибок никаких не было? Не повезло что AV ни разу не возникло из-за 

 for row:= 1 to Form1.StringGrid1.RowCount do



Это сообщение отредактировал(а) northener - 14.8.2013, 13:52


--------------------
Но только лошади летают вдохновенно.
Иначе лошади разбились бы мгновенно!
PM MAIL   Вверх
Poseidon
Дата 14.8.2013, 13:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Delphi developer
****


Профиль
Группа: Комодератор
Сообщений: 5273
Регистрация: 4.2.2005
Где: Гомель, Беларусь

Репутация: 53
Всего: 133



Цитата(kami @  14.8.2013,  13:49 Найти цитируемый пост)
Запомните раз и навсегда - нельзя к визуальным компонентам обращаться из дополнительного потока.
kami, нормально у него там через Synchronize проходит обращение.


--------------------
Если хочешь, что бы что-то работало - используй написанное, 
если хочешь что-то понять - пиши сам...
PM MAIL ICQ   Вверх
Ablis
Дата 14.8.2013, 13:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 11
Регистрация: 13.4.2011

Репутация: нет
Всего: нет



Цитата

И ошибок никаких не было? Не повезло что AV ни разу не возникло из-за 

 for row:= 1 to Form1.StringGrid1.RowCount do


Я его искуственно увеличил:
Form1.StringGrid1.RowCount:= ProcessList.ItemCount+1;
Поэтому могу себе позволить обращаться в цикле так smile 
PM MAIL   Вверх
Poseidon
Дата 14.8.2013, 13:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Delphi developer
****


Профиль
Группа: Комодератор
Сообщений: 5273
Регистрация: 4.2.2005
Где: Гомель, Беларусь

Репутация: 53
Всего: 133



Цитата(Ablis @  14.8.2013,  13:45 Найти цитируемый пост)
после отработки потока, в таблицу выводится только строка на которой стоит фокус
Мне почему-то кажется, что это из-за танцев с конвой...



--------------------
Если хочешь, что бы что-то работало - используй написанное, 
если хочешь что-то понять - пиши сам...
PM MAIL ICQ   Вверх
Ablis
Дата 14.8.2013, 14:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 11
Регистрация: 13.4.2011

Репутация: нет
Всего: нет



Цитата

Мне почему-то кажется, что это из-за танцев с конвой...


Так я вроде к ней напрямую не обращаюсь..
Пробовал добавить и Repaint; и Refresh; - результат тотже.
PM MAIL   Вверх
Ablis
Дата 14.8.2013, 18:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 11
Регистрация: 13.4.2011

Репутация: нет
Всего: нет



Цитата

Запомните раз и навсегда - нельзя к визуальным компонентам обращаться из дополнительного потока.
Многопоточность - как это делается в Delphi 

Перечитал  статью. Оказывается я ее уже когда-то давно читал, но вроде на английском языке. Так я и использую Synchronize для обращения к VCL из потока, а более сложные варианты мне не нужны, грубо говоря, моя задача сделать программу отзывчивой к действиям пользователя во время длительной операции. Пользуюсь delphi xe4, а в нем потоки перетерпели многочисленные изменения, да и потокозащищенность тех же VCL возросла.
PM MAIL   Вверх
Illusion Dolphin
Дата 14.8.2013, 20:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Участник Клуба
Сообщений: 1198
Регистрация: 3.5.2003

Репутация: 36
Всего: 63



Цитата

Я его искуственно увеличил:
Form1.StringGrid1.RowCount:= ProcessList.ItemCount+1;
Поэтому могу себе позволить обращаться в цикле так smile  

Что-то мне кажется, что в любом случае, как бы вы не увеличивали у себя там что-то, всё равно
Код

Form1.StringGrid1.Rows[Form1.StringGrid1.RowCount]

Сделает AV


--------------------
В мире всего две бесконечности: вселенная и человеческая глупость... На счёт вселенной я не уверен.
Шифрование и организация фотографий - Photo Database 4.5
PM MAIL WWW ICQ   Вверх
Ablis
Дата 14.8.2013, 22:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 11
Регистрация: 13.4.2011

Репутация: нет
Всего: нет



Цитата

Что-то мне кажется, что в любом случае, как бы вы не увеличивали у себя там что-то, всё равно
Код

Form1.StringGrid1.Rows[Form1.StringGrid1.RowCount]


Сделает AV 


Благодарю, не углядел. Оказывается, без исключения, я могу вывести текст в любую ячейку, даже несуществующую smile 
Но исправление на RowCount-1 конечно же исправляет работу программы, но вот проблему с выводом в потоке никак не решает.
PM MAIL   Вверх
Illusion Dolphin
Дата 14.8.2013, 23:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Участник Клуба
Сообщений: 1198
Регистрация: 3.5.2003

Репутация: 36
Всего: 63



Цитата

Но исправление на RowCount-1 конечно же исправляет работу программы, но вот проблему с выводом в потоке никак не решает. 

Что именно исправляет и что не исправляет? В студию код исправленный и картинку того, что не исправлено.

Добавлено через 59 секунд
Цитата

Оказывается, без исключения, я могу вывести текст в любую ячейку, даже несуществующую

ну а это до поры до времени, потом будет падение программы, 100%


--------------------
В мире всего две бесконечности: вселенная и человеческая глупость... На счёт вселенной я не уверен.
Шифрование и организация фотографий - Photo Database 4.5
PM MAIL WWW ICQ   Вверх
Чучмек
Дата 14.8.2013, 23:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


НЭТ БИЛЭТ
**


Профиль
Группа: Участник
Сообщений: 841
Регистрация: 11.5.2008
Где: СССР

Репутация: 14
Всего: 41



Ablis, метод, вызываемый через Synchronize - выполняется в контексте основного потока.
Соответственно, пока выполняется ShowResult - будет блокироваться приложение, в том числе и прорисовка грида.


--------------------
умную мысль держи при себе, а дурной - поделись с другими 
PM MAIL   Вверх
Ablis
Дата 15.8.2013, 12:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 11
Регистрация: 13.4.2011

Репутация: нет
Всего: нет



Цитата

Ablis, метод, вызываемый через Synchronize - выполняется в контексте основного потока.
Соответственно, пока выполняется ShowResult - будет блокироваться приложение, в том числе и прорисовка грида. 


C чего Вы это решили? Метод, вызываемый через Synchronize выполняется от того потока от которого был запущен, но способен изменять VCL основного потока через блокировки. Но эти блокировки, не блокируют приложение, так как приложение остается отзывчивым к действиям пользователя. Блокируются лишь методы вывода, но никак не, например, канва. Да и то, те методы, которые не выполняются в процессе блокировки, ставятся в очередь. Для работы с ней, например есть CheckSynchronize вызов которой приводит к выполнению всех методов, находящихся в данный момент в очереди SyncList, и возвращению управления из всех методов Synchronize, вызванных вторичными потоками.   

Цитата

Что именно исправляет и что не исправляет? В студию код исправленный и картинку того, что не исправлено.


Пожалуйста:

Код

procedure TProcessInfo.ShowResult;
var
 row,temp,max,temp1,max1:integer;
begin
  Form1.StringGrid1.RowCount:= ProcessList.ItemCount+1;
  max:= 0;
  max1:= 0;
  for row:= 1 to Form1.StringGrid1.RowCount-1 do
   Form1.StringGrid1.Rows[row].Clear();
  for row:= 1 to Form1.StringGrid1.RowCount-1 do
   with Form1.StringGrid1 do
    begin
      if ProcessList.pData[row-1].ProcessName<>'' then
       begin
         Cells[0, row]:= String(ProcessList.pData[row-1].ProcessName);
         Cells[1, row]:= IntToStr(ProcessList.pData[row-1].ProcessId);
         Cells[2, row]:= BoolToStr(ProcessList.pData[row-1].Visible);
         Cells[4, row]:= ProcessList.pData[row-1].Path;
         temp:= canvas.textWidth(cells[4, row]);
         temp1:= canvas.textWidth(cells[0, row]);
         if temp1>max1 then max1:= temp1;
         if temp>max then max:= temp;
         colWidths[4]:= max + gridLineWidth + 2;
         colWidths[0]:= max1 + gridLineWidth + 2;
       end;
    end;
end;


Результат - http://s2.ipicture.ru/uploads/20130815/SlEU8K14.jpg
Или, если я ставлю фокус в другую ячейку ПЕРЕД вызовом потока - http://s2.ipicture.ru/uploads/20130815/SXMfF13W.jpg

Но тем не менее, когда я переписал код так:

Код

procedure TProcessInfo.ShowResult;
var
 i: integer;
begin
  for I:= 0 to ProcessList.ItemCount-1 do
   with Form1.StringGrid1 do
    begin
      Cells[0, i+1]:= ProcessList.pData[i].ProcessName;
      Cells[1, i+1]:= IntToStr(ProcessList.pData[i].ProcessId);
      Cells[2, i+1]:= BoolToStrEx(ProcessList.pData[i].Visible);

      Cells[4, i+1]:= ProcessList.pData[i].Path;
      RowCount:= RowCount+1;
    end;
end;


Все заработало smile  - http://s2.ipicture.ru/uploads/20130815/jm72YiUQ.jpg
Так что намудрил я что-то с выводом в StringGrid прошлый раз.
Illusion Dolphin, еще раз благодарю, за наставление на истинный путь.
PM MAIL   Вверх
Ablis
Дата 15.8.2013, 12:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 11
Регистрация: 13.4.2011

Репутация: нет
Всего: нет



И напоследок, полностью рабочий код:

Код

procedure TProcessInfo.ShowResult;
var
 i,temp,max,temp1,max1: integer;
begin
  temp:=0;
  max:=0;
  temp1:=0;
  max1:=0;
  for I:= 1 to Form1.StringGrid1.RowCount-1 do
   Form1.StringGrid1.Rows[i].Clear;
  Form1.StringGrid1.RowCount:= 1;
  for I:= 0 to ProcessList.ItemCount-1 do
   with Form1.StringGrid1 do
    begin
      Cells[0, i+1]:= ProcessList.pData[i].ProcessName;
      Cells[1, i+1]:= IntToStr(ProcessList.pData[i].ProcessId);
      Cells[2, i+1]:= BoolToStrEx(ProcessList.pData[i].Visible);

      Cells[4, i+1]:= ProcessList.pData[i].Path;
      RowCount:= RowCount+1;
      temp:= Canvas.TextWidth(Cells[0, i+1])+ 8;
      if temp > max then max:= temp;
      temp1:= Canvas.TextWidth(Cells[4, i+1])+ 8;
      if temp1 > max1 then max1:= temp1;
    end;
  Form1.StringGrid1.ColWidths[0]:= max;
  Form1.StringGrid1.ColWidths[4]:= max1;
end;


Работает и очистка строк и выравнивание по нужным для меня столбцам.
Спасибо всем откликнувшимся, тему можно закрывать.
PM MAIL   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Delphi: Общие вопросы"
SnowyMetalFan
bemsPoseidon
Rrader

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Литературу по Дельфи обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь
  • 90% ответов на свои вопросы можно найти в DRKB (Delphi Russian Knowledge Base) - крупнейшем в рунете сборнике материалов по Дельфи


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Snowy, MetalFan, bems, Poseidon, Rrader.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Delphi: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0683 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.