Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Начинающим";
Текущий архив: 2008.05.18;
Скачать: [xml.tar.bz2];

Вниз

потоки   Найти похожие ветки 

 
Аврам   (2008-04-15 21:43) [0]

на форме валяется грид, заполненные данными.
строчек ~20-25 не больше.
по началу написал процедуру которая брала по очереди данные из каждой строчки и анализировала их. потом пришло в голову сделать все это дело через потоки, т.е. загружать например 10 потоков обрабатывать данные, потом по мере анализ освободившиеся потоки начинали обрабатывать следующие данные из грида, пока не проанализируются все.
можно ли так делать? если нет то почему? и как делать грамотней в этом случае?
решение о использовании потоков появилось когда попробовал запустить потоки по сразу всем данным типо того:
for i:=0 to grid.rowount -1 do
begin
     gg := txz.create;
   try
     with gg do
     begin
       Inc(FThreadRefCount);
       Resume;
     end;
   except on EConvertError do
     begin
       gg.Free;
       ShowMessage("That is not a valid number!");
     end;
   end;
end;
end;

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

Жду ответов и советов, спасибо!


 
Palladin ©   (2008-04-15 22:03) [1]

и из-за 20-25 строчек ты решил заморочится на распараллеливании обработки?
это из пушки по воробьям...


 
Аврам   (2008-04-15 22:05) [2]

20-25 это неверные данные. строчек много больше.


 
Аврам   (2008-04-15 22:09) [3]

у меня такой вопрос: я сделал так, поток берет первую строчку и затем удаляет ее, следующий также и т.д.
правильно ли это?как делать правильно?


 
Palladin ©   (2008-04-15 22:10) [4]

:)) я просто непонимаю, как можно расчитывать на грамотный совет, по ложным данным

уточняй сразу, где там еще неверные данные?


 
Reindeer Moss Eater ©   (2008-04-15 22:13) [5]

как делать правильно?

правильно грохнуть все разом.


 
Palladin ©   (2008-04-15 22:13) [6]

:)) я просто непонимаю, как можно расчитывать на грамотный совет, по ложным данным

уточняй сразу, где там еще неверные данные?


 
Palladin ©   (2008-04-15 22:18) [7]

прошу прощения за дубль, ie mobile млин...


>Аврам (15.04.08 22:09) [3]

не стоит на поток обработки вешать работу с vcl объктами...  кесарю кесарево... я бы организовал монитор поточной обработки (тоже поток)...


 
Аврам   (2008-04-15 22:18) [8]

таперь строчек будет 1000*n :))))
использвую грид потому что:
| P | Z |
|__________
| 5 | 0.1     |
| 5 | 0.01   |
| 5 | 0.2     |
| 5 | 0.6     |
| 5 | 0.009 |
| 6 | 0.1     |
| 6 | 0.3     |
| 6 | 0.0003|

основной параметр есть P, т.е. потоки забирают все эти данные и пока налазят то какой то закончит первым анализ, и как только он закончит то все остальные потоки которые аналязят строчки с этим параметром P надо вырубить т.к. они уже не имеют интереса для дальнейших рассчетов.
т.е. для P = 5 есть 1000 строк, взяли их на анализ 1000 потоков. затем какой то первый поток закончил анализ и вывел результат, сразу же надо выключить все остальные, которые анализируют данные с параметро P = 5. и так для каждого.


 
Аврам   (2008-04-15 22:20) [9]


> не стоит на поток обработки вешать работу с vcl объктами.
> ..  кесарю кесарево... я бы организовал монитор поточной
> обработки (тоже поток)...


не понимаю что значит "монитор поточной обработки", может имеется ввиду использование Synchronize в потоке?


 
Palladin ©   (2008-04-15 22:21) [10]

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


 
Аврам   (2008-04-15 22:23) [11]

для этой программы заказчик выделил отдельный компьютер!!! :))) так что все норм)
Спасибо за ответы!


 
Аврам   (2008-04-15 22:28) [12]

я так понимаю что у меня должен в памяти создаваться список потоков с ихними хенделами и параметро P, и уничтожать их по мере появления данных..прально?


 
MetalFan ©   (2008-04-15 22:37) [13]

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


 
Palladin ©   (2008-04-15 22:37) [14]

если никто не напишет, то завтра напишу тебе примерную схему пула потоков и его мониторинга...  на IE5 mobile  писать больше 10 сток кода это лучше сразу повесится...


 
Аврам   (2008-04-15 22:43) [15]


> MetalFan ©   (15.04.08 22:37) [13]
> нельзя работать с визуальными компонентами из доп.потоков.
> ..

я использую Synchronize для получения данных из vcl.


> Palladin ©   (15.04.08 22:37) [14]
> если никто не напишет, то завтра напишу тебе примерную схему
> пула потоков и его мониторинга...  на IE5 mobile  писать
> больше 10 сток кода это лучше сразу повесится...


ок, спасибо!


 
Dennis I. Komarov ©   (2008-04-16 10:16) [16]

Нет, конечно строка строке рознь но из пушки "ты каким номером палил?" (С) Кузьмич
Может нафиг эти треды? Ну не вижу я смыслу в них тут. Ку?


 
Сергей М. ©   (2008-04-16 10:20) [17]


> как делать грамотней в этом случае?


см. все касаемое тред-пула


 
Riply ©   (2008-04-16 10:23) [18]

> [16] Dennis I. Komarov ©   (16.04.08 10:16)
> Может нафиг эти треды? Ну не вижу я смыслу в них тут. Ку?

Ничего то ты не понимаешь :)
Ясно же сказано: "для этой программы заказчик выделил отдельный компьютер!!!"
Надо "осваивать" выделенные средства, а то больше не выделят :)


 
Dennis I. Komarov ©   (2008-04-16 11:15) [19]

> [18] Riply ©   (16.04.08 10:23)

while true do begin end;- освавает на 100% :)


 
tesseract ©   (2008-04-16 11:20) [20]


> я использую Synchronize для получения данных из vcl.


На кой тогда потоки ? А вообще может данные не из грида брать? А из какого-то внешнего источника ? Проверять и выводить в твой грид.


 
Palladin ©   (2008-04-16 11:21) [21]


> Аврам   (15.04.08 22:18) [8]

не понял юмора, они что, ты что хочешь заставить потоки играть в "кто быстре" чтоли? на кой другие то потоки будут работать с P=5 если все равно "должен остаться только один!" (С) маклауд


 
ANB   (2008-04-16 11:58) [22]

Классика распараллелки (примеров не просить, они все равно на Pl/SQL и сильно не помогут, но идея та же).
1. Подготовить более менее однородный список данных для обработки. Строки списка не должны зависеть друг от друга, т.е. должно быть все равно в каком порядке их обрабатывать.
2. Если он достаточно здоровый, что последовательное выполнение займет много времени, и при этом у вас имеется комп с несколькими процессами/ядрами (иначе эффекта все равно не будет, у нас эффект есть, но процессоров на сервере - 64), то начинаем заниматься распараллеливанием.
3. Определяем по количеству данных количество параллельных процессов (их не имеет смысла все равно делать более числа реальных процессоров/ядер).
4. Распределяем строки списка по процессам.
5. Подготовливаем задания/треды. Каждому треду копируем его кусок списка(мона брать и из общей кучи, но при этом нужно решить проблему потокобезопасности, мы этим не заморачиваемся - за нас уже все сделал оракл)
6. Стартуем задания и мониторим ход их выполнения. Обмениваться данными между потоками и монитором лучше всего через PostMessage - меньше тормозов и не надо ждать синхронных ответов. Не надо делать обмен информационными сообщениями слишком частым. В цикле ожидания монитора обязательно либо воткнуть слип хотя бы на 200 мс, либо юзать модальную форму (это не ко мне).


 
Аврам   (2008-04-16 12:22) [23]

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


 
Dennis I. Komarov ©   (2008-04-16 12:49) [24]

> [23] Аврам   (16.04.08 12:22)

Должен один отвечать за GUI, второй обрабатывать данные и выводить результаты на GUI. В данном случае обработку данных можно поручить первому. ИМХО!


 
Аврам   (2008-04-16 13:23) [25]


> Dennis I. Komarov

не понял,вы предлагает сделать всего два потока?
к сожалению опыт работы с потоками у меня очень мал, просьба отвечать более ясно, а то возникают новые вопросы.
не понимаю чем предложенная мной конструкция неправильна.
с 10-20 потоков аналязят данные,если какой то поток нашел получил результат, то выводит его на vcl, а другой единственный поток который мониторит получения результатов и состояния потоков (ведь какие то потоки просто закончат работу не найдя результата) просто вырубает группу потоков, чтобы их место заняли новые.


 
Dennis I. Komarov ©   (2008-04-16 13:27) [26]

> [25] Аврам   (16.04.08 13:23)

На кой ляд тебе вообще они понадобилися?


 
Аврам   (2008-04-16 13:39) [27]

для того чтобы быстрее получать нужные мне результаты.


 
Сергей М. ©   (2008-04-16 13:40) [28]


> чтобы быстрее


Мультипоточность не увеличивает сквозную производительность алгоритма приложения.


 
Dennis I. Komarov ©   (2008-04-16 13:42) [29]

> [27] Аврам   (16.04.08 13:39)

Сколько времени занимает обработка данных в одном потоке?


 
Аврам   (2008-04-16 13:56) [30]

в зависимости от кол-ва входных данных. в среднем в моей выборке часов 5 (дело в том что на сотню записей приходится один результат, он может быть и 99 по счету, а все до этого будут считаться и ничего не находить, а этот 99 поток который будет результирующим посчитается очень быстро и работа других с 1-98,100 - просто ненужны и их можно будет вырубить), я проверил запустил сотню потоков одновременно и специально засунул строчку с быстрым результатом. через 10 сек в memo добавился результат. что очень быстро для меня), но в диспетчере задач приложение все еще было достаточно загруженно 20мб, и постепенно уменьшалась.т.е. потоки другие еще работали. вот их нуно как то уничтожить)


 
Dennis I. Komarov ©   (2008-04-16 14:03) [31]

> [30] Аврам   (16.04.08 13:56)

Ну Terminate им и все. Но мне кажется тут надо логику исправлять. Вобщем надо исходные данные, а не [0]


 
Аврам   (2008-04-16 15:31) [32]

форма:
procedure TForm1.Button1Click(Sender: TObject);
var
 i:integer;
 gg:txz;
begin
for i:=0 to 50 do
begin
     gg := txz.create;
   try
     with gg do
     begin
       Inc(FThreadRefCount);
       Resume;
     end;
   except on EConvertError do
     begin
       gg.Free;
       ShowMessage("That is not a valid number!");
     end;
   end;
end;

end;

поток:
type
 TXZ = class(TThread)
 private
   { Private declarations }
 protected
   s:string;
   procedure start;
   procedure stop;
   procedure update;
   procedure Execute; override;
 public
       constructor Create;
 end;

constructor TXZ.Create;
begin
 inherited Create(True); //Созданный поток создается в приостановленном состоянии
 Self.Priority := tpNormal; //Очень высокий приоритет
 Resume;
end;

function DeleteGridRow( AGrid: TStringGrid; ARow: integer ): boolean;
var
i: integer;
begin
result := assigned( AGrid ) and
(AGrid.RowCount > AGrid.FixedRows) and
(ARow >= AGrid.FixedRows ) and
(ARow < AGrid.RowCount);
if not Result then Exit;
for i := ARow to AGrid.RowCount - 2 do
AGrid.Rows[i].Assign(AGrid.Rows[i+1]);
if AGrid.RowCount > (AGrid.FixedRows)+1 then
AGrid.RowCount := AGrid.RowCount -1
else
AGrid.Rows[AGrid.FixedRows].Clear;
end;

procedure TXZ.Execute;
var
 list:string;
begin
 Synchronize(start);
 ...
 // код анализа, довольно громозкий
 ...
 if result = -1 then
   Synchronize(update);
end;

procedure TXZ.start;
begin
s := form1.grid.cells[0,0];
DeleteGridRow(form1.grid,0);
end;

procedure TXZ.update;
begin
form1.ListBox2.Items.Add(s);
end;


 
Dennis I. Komarov ©   (2008-04-16 15:42) [33]

> [32] Аврам   (16.04.08 15:31)

Ну это конечно все ужасно... :)

Начнем с логики

Есть 20000 строк (не советую их в Grid сувать но не в том суть)
...
пиши далее


 
Аврам   (2008-04-16 16:07) [34]

я очень благодарен что мне помагаете! Спасибо!
значит так...Постараюсь описать всю задачу.
Count := 100;
Скажем заранее создан список каких то значений. Например
| id | name | NY | param1 | param2 |
| 1 | t1      |      | 0,111   | 4,1       |
| 2 | t2      |      | 0,002   | 5,1       |
| 3 | t3      |      | 0,123   | 2,1       |
| 4 | u1      |      | 0,312   | 4,5       |
| 5 | u2      |      | 0,324   | 3,8       |
| 6 | u3      |      | 0,213   | 7,3       |
|...| ...       |      |  ....     |  ....      |

кол-во столбцев param* может быть и больше двух.

попробовав используя потоки.
для первой строчки создал список из count(100) строчек и создал как показывал выше 100 потоков. ловольно быстро получил результат :) но остальные потоки продолжали работать.
Я так понимаю что хорошо бы создавать для каждой строчки группу потоков и при нахождении выключать ее.
Еще не понятно, как быть с этим делом...создавать 100 потоков или по 10 потоков и освобожденным давать новые данные на анализ...
С уважением А.
обычная процедура как я делал с самого начала без потоков брала первую строчку из списка и пускала в процедуре анализ этой строки. Переменная count как раз говорит сколько раз надо проверить каждую строчку.
Т.е. 100 раз первую сто раз вторую.
типа for i:=0 to count -1 do begin
Если найден результат по заданым мной критериям и i= 19  то в поле NY мы добавляем результат например 0,0102 и переходим к анализу строчки с id =2 и т.д.


 
Аврам   (2008-04-16 16:10) [35]

тач пад глючит у ноута
правильней так:

очень благодарен что мне помагаете! Спасибо!
значит так...Постараюсь описать всю задачу.
Count := 100;
Скажем заранее создан список каких то значений. Например
| id | name | NY | param1 | param2 |
| 1 | t1      |      | 0,111   | 4,1       |
| 2 | t2      |      | 0,002   | 5,1       |
| 3 | t3      |      | 0,123   | 2,1       |
| 4 | u1      |      | 0,312   | 4,5       |
| 5 | u2      |      | 0,324   | 3,8       |
| 6 | u3      |      | 0,213   | 7,3       |
|...| ...       |      |  ....     |  ....      |

кол-во столбцев param* может быть и больше двух.

обычная процедура как я делал с самого начала без потоков брала первую строчку из списка и пускала в процедуре анализ этой строки. Переменная count как раз говорит сколько раз надо проверить каждую строчку.
Т.е. 100 раз первую сто раз вторую.
типа for i:=0 to count -1 do begin
Если найден результат по заданым мной критериям и i= 19  то в поле NY мы добавляем результат например 0,0102 и переходим к анализу строчки с id =2 и т.д.

попробовав используя потоки.
для первой строчки создал список из count(100) строчек и создал как показывал выше 100 потоков. ловольно быстро получил результат :) но остальные потоки продолжали работать.
Я так понимаю что хорошо бы создавать для каждой строчки группу потоков и при нахождении выключать ее.

Еще не понятно, как быть с этим делом...создавать 100 потоков или по 10 потоков и освобожденным давать новые данные на анализ...
С уважением А.


 
ANB   (2008-04-16 16:13) [36]

Ни хрена не понял.
1) зачем проверять строку 100 раз. ?
2) какова цель этих проверок ?
т.е. нужно найти первую попавшуюся "проверенную" строку ? Или "проверить" все строки ?

ЗЫ. ИМХО : скорее всего надо бы загрузить исходные данные в таблицу БД и через минуту получить ответ обычным запросом.


 
ANB   (2008-04-16 16:16) [37]


> Еще не понятно, как быть с этим делом...создавать 100 потоков
> или по 10 потоков и освобожденным давать новые данные на
> анализ...

Опять таки ИМХО : если до этого не работал с потоками, то скорее всего вместо правильного результата, полученного последовательной обработкой, ты получишь непонятные AV и снова придешь на форум.
А перво-наперво : не обращайся из потоков к объектам на форме.


 
Dennis I. Komarov ©   (2008-04-16 16:26) [38]

Алгоритм анализа не озвучен. Ни о чем... Логика в нем!!!


 
Аврам   (2008-04-16 16:30) [39]

все говорят не обращаться из потоков к объектам на форме.
а если мне надо взять инфу из какого то списка, ка ктогда быть?


 
Dennis I. Komarov ©   (2008-04-16 16:33) [40]

> [39] Аврам   (16.04.08 16:30)

А почему инфа должна храниться на форме?


 
Аврам   (2008-04-16 16:35) [41]

ну если создать tstringlist - то это тоже будет объект формы....но я не уверен, потому и спрашиваю.


 
Dennis I. Komarov ©   (2008-04-16 16:46) [42]

> [41] Аврам   (16.04.08 16:35)

Кто заставляет там хранить данные

+

[38]


 
Palladin ©   (2008-04-16 16:58) [43]


> ANB
> А перво-наперво : не обращайся из потоков к объектам на
> форме.

обоснуй. я вот обращаюсь...


> Аврам

если ты хочешь устроить "царя горы" давай сразу проясним количественную составляющую потоков. сколь много может поступить данных с одинаковым P?


 
Аврам   (2008-04-16 17:02) [44]

с одинаковым p ~ 100-150.

если не хранит даныне на форме то где и как? то что нельзя обращаться к vcl я слышал много раз, а почему и как правильно не видел нигде)))))


 
Palladin ©   (2008-04-16 17:06) [45]


> с одинаковым p ~ 100-150.

ok, если это так... дальше, алгоритм обработки линейный или циклический?


 
Аврам   (2008-04-16 17:14) [46]

затрудняюсь сказать, так как плохо понимаю терминологию. (не знаю просто).


 
Palladin ©   (2008-04-16 17:16) [47]


> Аврам   (16.04.08 17:14) [46]

циклы for to do, while do, repeat until используются в вычислениях или одна только формула?


 
Palladin ©   (2008-04-16 17:21) [48]

я просто хочу выяснить, на сколько тяжел весь алгоритм в целом и есть ли в нем контрастно тяжеленные места?


 
Dennis I. Komarov ©   (2008-04-16 17:22) [49]

> [48] Palladin ©   (16.04.08 17:21)

Партизаны не сдаются!!!


 
Аврам   (2008-04-16 17:25) [50]

забыл сказать еще одну важную весчь,в одном месте еще есть загрузка некоторых данных с интернета (есть сервер с данными, которые постоянно меняются).
это выглядит так page := get(***);в page загружается страница и беруться оттуда некоторые данные парсингом.


 
Аврам   (2008-04-16 17:26) [51]

к сожалению я не все исходные тексты могу выкладывать.


 
Palladin ©   (2008-04-16 17:33) [52]


> Аврам   (16.04.08 17:26) [51]

я не прошу тебя выкладывать тексты... раз ты определить распределение тяжести по алгоритму не в состоянии, то придется в нем на каждый чих с данными (практически через каждую строчку) вставлять следующее
If Terminated Then Exit; , а так же окаймить метод execute скобками try finally end, для корректного освобождения взятых в процессе ресурсов при exit

ты готов к этому?


 
Аврам   (2008-04-16 17:35) [53]

готов.
я предпологал что есть возможность послать группе потоков принудительный выход, ьез использования If Terminated Then Exit;


 
Palladin ©   (2008-04-16 17:37) [54]


> Аврам   (16.04.08 17:35) [53]

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

хорошо раз готов, жди...


 
Dennis I. Komarov ©   (2008-04-16 17:38) [55]

> [51] Аврам   (16.04.08 17:26)

50 постов спустя появляются все новые и новые исходные :(


 
Palladin ©   (2008-04-16 18:38) [56]

Type
TWorkThread=Class(TThread)
 Private
  m_theEndFlagP:TMultiReadExclusiveWriteSynchronizer;
  m_bEndFlag:Boolean;
  m_pData:Pointer;
  m_theData:TStringList;

  Function lcGetEndFlag:Boolean;
 Protected
  Procedure Execute; Override;
 Public
  Constructor Create(Const p_theData:TStrings);
  Destructor Destroy; Override;

  Property EndFlag:Boolean Read lcGetEndFlag;
  Property Data:Pointer Read m_pData;
End;

TMonitorThread=Class(TThread)
 Private
  m_theStringGrid:TStringGrid;
  m_nDropLinesTo:Integer;
  Procedure DropLines;
 Protected
  Procedure Execute; Override;
 Public
  Constructor Create(p_theStringGrid:TStringGrid);
End;

Constructor TWorkThread.Create;
Begin
m_theEndFlagP:=TMultiReadExclusiveWriteSynchronizer.Create;
m_theData:=TStringList.Create;
m_theData.AddStrings(p_theData);
m_bEndFlag:=False;
Inherited Create(False);
End;

Destructor TWorkThread.Destroy;
Begin
Inherited;
m_theData.Free;
m_theEndFlagP.Free;
End;

Procedure TWorkThread.Execute;
Var
i:Integer;
Begin
// берем ресурсы
Try
 For i:=0 to Random(10*1000)-1 Do
  Begin
   Sleep(100); // создаем видимость работы в поте интерфейса
   If Terminated Then Exit;
  End;

 m_theEndFlagP.BeginWrite;
 Try
  m_bEndFlag:=True;
 Finally
  m_theEndFlagP.EndWrite;
 End;
Finally
 // освобождаем ресурсы
End;
End;

Function TWorkThread.lcGetEndFlag;
Begin
m_theEndFlagP.BeginRead;
Try
 Result:=m_bEndFlag;
Finally
 m_theEndFlagP.EndRead;
End;
End;

Const
CONST_NOMER_OF_COLUMN_WITH_P=1;

Procedure TMonitorThread.Execute;
Var
theListOfThreads:TList;

Procedure _FreeThreadsList;
Var
 i:Integer;
Begin
 For i:=0 to theListOfThreads.Count-1 Do TThread(theListOfThreads).Free;
 theListOfThreads.Clear;
End;

Function _CreateThreads:Boolean;
Var
 n,P:Integer;
Begin
 Result:=m_theStringGrid.RowCount<>0;
 If Not Result Then Exit;
 n:=0;
 P:=StrToInt(m_theStringGrid.Cells[CONST_NOMER_OF_COLUMN_WITH_P,n]);
 While True Do
  Begin
   Result:=Not Terminated;
   If Not Result Then Exit;
   theListOfThreads.Add(TWorkThread.Create(m_theStringGrid.Rows[n])); Inc(n);
   If (n=m_theStringGrid.RowCount) Then Begin m_nDropLinesTo:=n-1; Exit; End Else
   If StrToInt(m_theStringGrid.Cells[CONST_NOMER_OF_COLUMN_WITH_P,n])<>P Then Begin m_nDropLinesTo:=n-1; Exit; End;
  End;
End;

Function _WaitForThreads:Boolean;
Var
 i:Integer;
Begin
 i:=0;
 While True Do
  Begin
   Result:=Terminated;
   If Result Then Exit;
   If TWorkThread(theListOfThreads[i]).EndFlag Then
    Begin
     ChegoNibudDelaemS(TWorkThread(theListOfThreads[i]).Data);
     Exit;
    End;
   If i=theListOfThreads.Count Then i:=0;
   Sleep(100);
  End;
End;

Begin
theListOfThreads:=TList.Create;
Try
 While True Do
  Begin
   If Terminated Then Exit;
   m_nDropLinesTo:=-1;
   If Not _CreateThreads Then Exit;
   If _WaitForThreads Then Exit;
   Synchronize(DropLines);
   _FreeThreadsList;
  End;
Finally
 _FreeThreadsList;
 theListOfThreads.Free;
End;
End;

Constructor TMonitorThread.Create;
Begin
m_theStringGrid:=p_theStringGrid;
Inherited Create(False);
End;

Procedure TMonitorThread.DropLines;
Var
j,i:Integer;
Begin
If m_nDropLinesTo=-1 Then Exit;
For i:=m_nDropLinesTo to m_theStringGrid.RowCount-1 Do
 For j:=0 to m_theStringGrid.ColCount-1 Do
  With m_theStringGrid Do Cells[j,i-m_nDropLinesTo]:=Cells[j,i];
With m_theStringGrid Do RowCount:=RowCount-m_nDropLinesTo;
End;


сюда еще нужно будет прикрутить оповещение монитора об уничтожении источника данных, TStringGrid"а

вроде бы нигде не ошибся...


 
Аврам   (2008-04-16 19:27) [57]

вах...спасибо! щас буду разбираться...))


 
Palladin ©   (2008-04-16 19:30) [58]


> вроде бы нигде не ошибся...

все таки ошибся... пропустил Inc(i) в Function _WaitForThreads:Boolean;


 
Аврам   (2008-04-16 19:53) [59]

Palladin, код который ты привел нужно вставлять в основном приложении или в отдельно созданном уните - потоке ?


 
Palladin ©   (2008-04-16 19:54) [60]


> Аврам   (16.04.08 19:53) [59]

куда хочешь туда и вставляй...


 
sniknik ©   (2008-04-16 20:08) [61]

афигеть... дополнительный компьютер под задачу которая считает данные в stringgrid-е, и тормозит изза потоков... лучше бы программиста наняли.


 
Аврам   (2008-04-16 20:25) [62]

sniknik, не тебе судить что лучше, если хочешь помочь, то помагай - буду благодарен, а говорить о том чего не знаешь - не стоит. Думаю ты меня понял. Чтобы подобные советы "нанять программиста" и нафига доп. комп. тут больше не обсуждались разъесню немного. Данные будут считыватья в течении 5-8 часов, и нужно постоянно наблюдать за происходящим. (получение результатов). Нашелся никем не используемый компьютер. вот его под это дело и дали. К этйо теме кол-во ком. и его мощность никак не относиться.
Спасибо всем за ответы и за советы.
Учусь. С уважением, А.


 
Palladin ©   (2008-04-16 20:29) [63]


>sniknik©(16.04.08 20:08) [61]

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


 
Аврам   (2008-04-16 20:42) [64]

Palladin, разбираюсь в коде, который ты мне дал, хочу понять что к чему.
Не все понятно, поэтому я постараюсь описать то что ты мне дал, а ты меня поправишь если что не так :)))

Поток TMonitorThread - это поток, который будет следить за потоками.
TWorkThread - поток, который берет данные из грида и обрабатывает их.

сначала я должен создать поток TMonitorThread и дать ему на съедение stringgrid:
var
 new:TMonitorThread;
begin
 new := TMonitorThread.Create(StringGrid1);
 try
    with new do
    begin
      Resume;
    end;
  except on EConvertError do
    begin
      new.Free;
      ShowMessage("That is not a valid number!");
    end;
  end;


дальше я должен создать потоки TWorkThread.
pot :=TWorkThread.Create(StringGrid1.Cols[0]);
  try
    with pot do
    begin
      Resume;
    end;
  except on EConvertError do
    begin
      pot.Free;
      ShowMessage("That is not a valid number!");
    end;
  end;

//ChegoNibudDelaemS(TWorkThread(theListOfThreads[i]).Data); закоментировал так как пока не знаю что здесь будет.

чувствую что делаю неправильно)


 
Palladin ©   (2008-04-16 20:45) [65]

звиняй, лекция будет уже только завтра... но будет


 
Аврам   (2008-04-16 20:57) [66]

спасибо, договорились ))


 
sniknik ©   (2008-04-16 21:08) [67]

> не все так безсмысленно, аффтар упомянул о получении данных по http, а это уже совсем другой разговор...
откуда угодно, stringgrid не для обработки данных, отображать, и только часть (!)  еще куда ни шло, да и то, гораздо для этого предпочтительнее dbgrig + dataset под данные.


 
Аврам   (2008-04-16 21:37) [68]

sniknik, у меня же не БД, анализируемые данные в дальнейшем ненужны.


 
Palladin ©   (2008-04-16 22:05) [69]


>sniknik©(16.04.08 21:08) [67]

про StringGrid согласен, но лично я бы заменил на ListView в виртульном режиме...


 
Palladin ©   (2008-04-16 22:05) [70]

:) тьфу блин, в виртуальном


 
sniknik ©   (2008-04-16 22:56) [71]

> но лично я бы заменил на ListView в виртульном режиме...
dataset быстрее и функциональнее. вот как в ListView будеш делать сортировку? (понятно не в самом, раз в виртуальном, а в том динамическом массиве что "под ним")
а индексы поддерживать? нужен быстрый поиск значения? фильтрация данных? и т.д.
dataset готовый компонент по работе с данными. в других же многое будет "велосипедоизобретательством".


 
Palladin ©   (2008-04-16 23:19) [72]

я тебя умоляю... при чем здесь индексирование? что ты индексировать собрался тут? быстрый поиск значения... какого значения? фильтрация данных... какая еще фильтрация? чего ты тут фильтровать то собрался?

а со своим любимым датасетом ты реально обвешиваешь набор входящих данных для расчета нафик никому ненужным функционалом... пойми, речь идет об fifo...


 
Palladin ©   (2008-04-16 23:23) [73]

хотя на счет fifo может быть я и неправ... надо будет завтра у аффтора уточнить происхождение данных и критичность упорядоченности при вхождении на обработку...


 
Palladin ©   (2008-04-16 23:29) [74]

в любом случае я тебе обеспечу производительность работы с данными в виртуальном режиме ListView гораздо более производительную чем при использовании DataSet"а


 
Аврам   (2008-04-16 23:53) [75]


>  надо будет завтра у аффтора уточнить происхождение данных
> и критичность упорядоченности при вхождении на обработку.
> ..

данные генеряться на этапе-1. критичность не важна, они и так поступают в определенном порядке и далее идут на обработку.
то о чем мы здесь говорим и о чем эта тема - это этап-2.


 
sniknik ©   (2008-04-17 00:30) [76]

> при чем здесь индексирование? что ты индексировать собрался тут? быстрый поиск значения... какого значения?
намеки на повторяющиеся до 100 раз поиски значения одной записи в других есть в > Аврам   (16.04.08 16:07) [34]
без индексов тяжелый поиск будет.

> фильтрация данных... какая еще фильтрация?
обычная. нужно например поиск этой кучи из 100 значений в данных, накладываешь фильтр вместо многочисленных поисков и получаешь нужное сразу.

> чего ты тут фильтровать то собрался?
вообщето ничего... (процесс "обработки" как был тайной так и остался. и, думаю останется)
но, были бы данные, а что из них фильтровать, найдется. данные вроде как есть и немало. 100 строк там у него предполагалось вроде, на поток, и 100 потоков. т.е. 10 000 записей.


 
Германн ©   (2008-04-17 01:02) [77]


> Palladin ©   (16.04.08 23:29) [74]
>
> в любом случае я тебе обеспечу производительность работы
> с данными в виртуальном режиме ListView гораздо более производительную
> чем при использовании DataSet"а
>

Тут я скорее поддержу Николая. В большинстве случаев всё уже разработано для БД. Ну а если я не прав, то ты, Тимур, имеешь все шансы на Нобель. :)


 
Аврам   (2008-04-17 01:11) [78]

причем тут фильтрация, индексирование и т.д.
все как делает Palladin как раз то что нужно. никаке бд, и тем более поиск мне не нужен.


 
Германн ©   (2008-04-17 01:47) [79]


> Аврам   (17.04.08 01:11) [78]
>
> причем тут фильтрация, индексирование и т.д.
> все как делает Palladin как раз то что нужно. никаке бд,
>  и тем более поиск мне не нужен.

А ты хто такой? И чего лезешь в дискуссию мастеров?
:)
Не в обиду будь. Ты создал ветку!. Но эта ветка получила иную жизнь.


 
Аврам   (2008-04-17 07:53) [80]

Как минимум автор темы, уже этого хватит. Пожалуйста лишнего на себя не берите. Я не претендую на статус мастера, и о каких обидах вы говорите, просто хамить здесь не зачем, я пришел за помощью на форум "Начинающим".
Как вы любите говорить для того чтобы поболтать сущ. другие разделы раз уж на то пошло.
С уважением, А.


 
sniknik ©   (2008-04-17 08:51) [81]

> Как минимум автор темы, уже этого хватит.
не хватит. автор темы бесполезен, и даже вреден, для обсуждения если он партизан. и может быть даже забанен, пофигу, тема им начатая будет "жить". пока есть интерес других участников.

> я пришел за помощью на форум "Начинающим".
имхо конечно, но как раз помощь тебя и не интересует, ты просто любишь "парить" людям мозг...

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

> Как вы любите говорить для того чтобы поболтать сущ. другие разделы раз уж на то пошло.
видиш ли, твоя ветка настолько не изобилует подробностями, бедна информацией о собственно задаче (метод решения -> перенос в потоки, задачей не является), что попросту провоцирует треп на эту тему. и давно уже она кандидат на перенос в "другие разделы раз уж на то пошло" конкретно в потрепаться. нехватает малости (возможно твоего ответа на вот этот пост, в практикуемом тобой стиле, опять без подробностей что делается).


 
ЦУП ©   (2008-04-17 09:35) [82]


> Аврам   (17.04.08 01:11) [78]


А скажи, это принципиально - отображение на форме такой кучи данных?

Если нет, то ты уже сам озвучивал, чт оможно использовать TStringList.
А ещё лучше - связный список. Накладных расходов будет меньше.


 
Palladin ©   (2008-04-17 09:49) [83]

Итак, начем"с разбор полетов :)

сначала

> Германн ©   (17.04.08 01:02) [77]
> sniknik ©   (17.04.08 00:30) [76]

понимаите, понимашь, ну вот возьмем конструкцию array of, зачем ее сделали? нафик она нужена то? Николай предлагает универсальное придуманное решение TDataSet. Давным давно уже все придумали. И индексацию, и фильтрацию.
Возьмем TList, да вот тоже непонятные аффтары Делфи, зачем нужен этот TList, когда есть универсальное придуманное решение TDataSet. Давным давно уже все придумали. И индексацию, и фильтрацию.
Возьмем TStringList. Это вообще не понятно, конечно же для хранения строк лучше использовать универсальное придуманное решение TDataSet. Давным давно уже все придумали. И индексацию, и фильтрацию.

Так вот, объясняю. Как выглядят данные аффтора и что он пытается организовать. Есть некий параметр P, для него есть набор однотипных данных для расчета, аффтар не желает обрабатывать их последовательно, я считал это нежелание абсолютно необоснованным до [30] и [50]го поста. Но в свете [30 и [50], мысль на счет распараллеливания очень даже имеет право на существование, более того это самый оптимальный вариант при таких условиях. Теперь вернемся к хранению данных. Как их следует хранить? Если я прав на счет структуры, а пока я не вижу никаких противоречий, то расскажу я аффтору, на основе его же рисунков, как же это сделать правильно.

Для начала надо продумать, как мы будем их отображать и в каком виде, есть два варианта. Плоский табличный либо небольшое двууровневое дерево
P -> Params для P. Бо от этого зависит как проще построить запись описания данных. В любом случае это должен быть либо TListView, либо Virtual TreeView (http://www.soft-gems.net/), бо первый имеет виртуальный режим работы, а второй по другому просто не умеет :).
Почему так важна виртуальность. Виртуальность позволит нам хранить записи в своих структурах не храня их в самих визуальных компонентах, они (визуальные компоненты) лишь обращаются к нам если им понадобится какое либо значение.


 
Palladin ©   (2008-04-17 09:49) [84]

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

Type
PLVDataRec=^TLVDataRec;
TLVDataRec=Record
 P:Integer; // наш любимый P
 Params:Array of Integer; // наши параметры, их может быть разное количество
 ... // какие нибудь еще данные связанные с P
End;

Var
theData:TList; // основной источник данных

Этот каноническое решение для работы со списками. Но еще немножко подумав, мы решаем, а зачем нам ненужный функционал TList, нам всего то нужно заполнить массив и последовательно удалять отработанные элементы. И приходим к такому решению, что еще более оптимальней.

Type
TLVDataRec=Record
 P:Integer; // наш любимый P
 Params:Array of Integer; // наши параметры, их может быть разное количество
 ... // какие нибудь еще данные связанные с P
End;

Var
a:Array of TLVDataRec; // основной источник данных, с обратным заполнением

Обратное заполнение означает - первый элемент является последним в массиве. И идти по массиву мы будем задом наперед. Почему так? А потому что не нужно будет заморачиватся на удалении отработанных элементов. SetLength и все.

Идем дальше. Организовать отображение данных в TListView (вид vsReport) это не проблемма. Оставлю аффтору на домашнее задание. Информации про его виртуальный режим в интернете выше крыши. Нас сейчас интересует как поменяется работа, вышенаписанной мной, схемы монитора и потоков. А сильно она и не поменяется. Лишь в области передачи данных, очереди посылки записи на обработку и обновления вида TListView.

Type
TLVDataRec=Record
 P:Integer; // наш любимый P
 Params:Array of Single; // наши параметры, их может быть разное количество
 // какие нибудь еще данные связанные с P
End;
TDataArray=Array of TLVDataRec;

Var
a:TDataArray; // основной источник данных, с обратным заполнением

Type
TWorkThread=Class(TThread)
 Private
  m_theEndFlagP:TMultiReadExclusiveWriteSynchronizer;
  m_bEndFlag:Boolean;
  m_pResultData:Pointer; // переименовал дабы небыло несуразностей
  m_prData:^TLVDataRec; // незачем копировать запись, работаем по ее адресу

  Function lcGetEndFlag:Boolean;
 Protected
  Procedure Execute; Override;
 Public
  Constructor Create(Const p_rData:TLVDataRec);
  Destructor Destroy; Override;

  Property EndFlag:Boolean Read lcGetEndFlag;
  Property Data:Pointer Read m_pResultData;
End;

TMonitorThread=Class(TThread)
 Private
  m_aDataRef:^TDataArray;// ссылка на исходный массив, именно ссылка иначе будет создана копия
  m_theListView:TListView; // трудяга визуализатор

  m_nDropLinesFrom:Integer; // мы работаем теперь с конца массива
  Procedure DropLines;
 Protected
  Procedure Execute; Override;
 Public
  Constructor Create(Const p_aData:TDataArray;p_theListView:TListView);
End;

Constructor TWorkThread.Create;
Begin
m_theEndFlagP:=TMultiReadExclusiveWriteSynchronizer.Create;
m_prData:=@p_rData;
m_bEndFlag:=False;
Inherited Create(False);
End;

Destructor TWorkThread.Destroy;
Begin
Inherited;
m_theEndFlagP.Free;
End;

Procedure TWorkThread.Execute;
Var
i:Integer;
Begin
// берем ресурсы
Try
 For i:=0 to Random(10*1000)-1 Do
  Begin
   Sleep(100); // создаем видимость работы в поте интерфейса
   If Terminated Then Exit;
  End;

 m_theEndFlagP.BeginWrite;
 Try
  m_bEndFlag:=True;
 Finally
  m_theEndFlagP.EndWrite;
 End;
Finally
 // освобождаем ресурсы
End;
End;

Function TWorkThread.lcGetEndFlag;
Begin
m_theEndFlagP.BeginRead;
Try
 Result:=m_bEndFlag;
Finally
 m_theEndFlagP.EndRead;
End;
End;

Procedure TMonitorThread.Execute;
Var
theListOfThreads:TList;

Procedure _FreeThreadsList;
Var
 i:Integer;
Begin
 For i:=0 to theListOfThreads.Count-1 Do TThread(theListOfThreads).Free;
 theListOfThreads.Clear;
End;

Function _CreateThreads:Boolean;
Var
 n,P:Integer;
Begin
 n:=Length(m_aDataRef^)-1;
 Result:=n<>-1;
 If Not Result Then Exit;
 P:=m_aDataRef^[n].P;
 While True Do
  Begin
   Result:=Not Terminated;
   If Not Result Then Exit;
   theListOfThreads.Add(TWorkThread.Create(m_aDataRef^[n])); Dec(n);
   If n=-1 Then Begin m_nDropLinesFrom:=n+1; Exit; End Else
   If m_aDataRef^[n].P<>P Then Begin m_nDropLinesFrom:=n+1; Exit; End;
  End;
End;

Function _WaitForThreads:Boolean;
Var
 i:Integer;
Begin
 i:=0;
 While True Do
  Begin
   Result:=Terminated;
   If Result Then Exit;
   If TWorkThread(theListOfThreads[i]).EndFlag Then
    Begin
     ChegoNibudDelaemS(TWorkThread(theListOfThreads[i]).Data);
     Exit;
    End;
   Inc(i); If i=theListOfThreads.Count Then i:=0;
   Sleep(100);
  End;
End;

Begin
theListOfThreads:=TList.Create;
Try
 While True Do
  Begin
   If Terminated Then Exit;
   m_nDropLinesFrom:=-1;
   If Not _CreateThreads Then Exit;
   If _WaitForThreads Then Exit;
   Synchronize(DropLines);
   _FreeThreadsList;
  End;
Finally
 _FreeThreadsList;
 theListOfThreads.Free;
End;
End;

Constructor TMonitorThread.Create;
Begin
m_aDataRef:=@p_aData;
m_theListView:=p_theListView;
Inherited Create(False);
End;

Procedure TMonitorThread.DropLines;
Begin
If m_nDropLinesFrom=-1 Then Exit;
SetLength(m_aDataRef^,m_nDropLinesFrom);
m_theListView.Items.Count:=Length(m_aDataRef^);
m_theListView.Refresh;
End;


вуаля...

и еще скажу на последок поклонникам БД: TDataSet идет лесом, в случае четкой структуры данных предназначенных для обработки и ни для чего более. Идеология TDataSet - отображение (не визуальное имеется ввиду, а в контексте делфи отображение) набора записей БД и предоставление гибкого (в плане зависимости от БД) основного функционала работы с ним. Вот решит аффтар или его шеф(ы), сделать входящий массив данных устойчивым и хранящемся в БД, тогда будет саааавсем другой разговор.

Путь Virtual TreeView, будет описан вечером, бо мне и свою работу работать надо :)


 
Anatoly Podgoretsky ©   (2008-04-17 10:05) [85]

> sniknik  (17.04.2008 08:51:21)  [81]

По уму и обсуждение.


 
sniknik ©   (2008-04-17 11:31) [86]

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


 
ANB   (2008-04-17 12:29) [87]


> обоснуй. я вот обращаюсь...

Можно и обращаться. Но если это делать корректно, то потоки будут ждать друг друга.


 
ANB   (2008-04-17 12:36) [88]


> БД то как раз никто и не предлагал.

Я предлагал. У меня подозрение, что БД выполнит алгоритм обработки намного шустрее и распараллелка просто не понадобится.


 
Palladin ©   (2008-04-17 12:39) [89]


> ANB   (17.04.08 12:29) [87]

Очень редкий случай, когда при распараллеливании не нужна синхронизация, а в случае синхронизации - всегда может возникнуть ситуация, когда один поток должен подождать пока не отработает какой то другой. Так что это в порядке вещей. И так категорически заявлять о запрете на обращение к VCL в потоках не нужно. Никак производительность, нормально спроектированной, многопоточной системы не будет страдать от этого.


> sniknik ©   (17.04.08 11:31) [86]

ну да... семейство inmemory dataset"ов никто не отменял...
но, как ты верно отметил по поводу "подходят для задачи", если собаке для выполнения, ее собачьих функций, понадобилась бы пятая нога я думаю она у нее была бы. а так, ну можно и пришить хирургически, или искусственную присобачить... :) а смысл?


 
ANB   (2008-04-17 12:47) [90]


> а смысл?

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


> Никак производительность, нормально спроектированной, многопоточной
> системы не будет страдать от этого.

Выделенное является главным.
Я не писал о полном запрете на работу с VCL из потоков. И если меня поняли не так - уточнил это в следующем посте.
Никто не запрещает сложить все данные для расчета в визуальный компонент и лезть через синхронизе к нему из тысячи потоков. Только быстрее чем один они скорее всего работать не будут.


 
sniknik ©   (2008-04-17 12:52) [91]

> а смысл?
имхо достаточный смысл, если там (что упоминалось) есть частый поиск значений одних данных в других.


 
Palladin ©   (2008-04-17 13:00) [92]


> sniknik ©   (17.04.08 12:52) [91]

перечитал [34] никаких намеков на поиск значений среди других не увидел...


> ANB   (17.04.08 12:47) [90]

а ты читал [30]? вдумчиво читал?


 
Dennis I. Komarov ©   (2008-04-17 13:05) [93]

> а в выборе оптимального метода решения задачи

А вот этого мы так и не узнаем, т.к. [38] и [51]


 
Palladin ©   (2008-04-17 13:09) [94]


> Dennis I. Komarov ©   (17.04.08 13:05) [93]

и ты [30] не понял... там есть ключевая фраза, которая и делает распаралелливание оптимальным решением...


 
sniknik ©   (2008-04-17 13:11) [95]

> Я предлагал. У меня подозрение, что БД выполнит алгоритм обработки намного шустрее и распараллелка просто не понадобится.
про нужность "распараллелки" согласен, единственное БД это всетаки дополнительные заботы. и если можно обойтись без нее, я бы постарался обойтись.

а каким образом оптимизировать обработку с помощью датасета или динамического массива под TreeView в принципе не суть важно. датасет просто потребует меньше усилий при больших возможностях.

> перечитал [34] никаких намеков на поиск значений среди других не увидел...
> обычная процедура как я делал с самого начала без потоков брала первую строчку из списка и пускала в процедуре анализ этой строки.
> Переменная count как раз говорит сколько раз надо проверить каждую строчку.
> Т.е. 100 раз первую сто раз вторую.
> типа for i:=0 to count -1 do begin
> Если найден результат по заданым мной критериям и i= 19  то в поле NY мы добавляем результат например 0,0102
> и переходим к анализу строчки с id =2 и т.д.
думаешь 100 раз проверка идет одной и той же строки? так сказать для гарантии результата?

p.s. бред это все, без четкого описания "обработки" автором. посему надо закругляться.


 
Dennis I. Komarov ©   (2008-04-17 13:17) [96]

> [94] Palladin ©   (17.04.08 13:09)

ну возможно...

НО

> p.s. бред это все, без четкого описания "обработки" автором.
> посему надо закругляться.


 
Palladin ©   (2008-04-17 13:17) [97]


> Т.е. 100 раз первую сто раз вторую.
> >типа for i:=0 to count -1 do begin


я вижу это так: у него просто два списка один как в [34], первого уровня, второй другой как [8] по P (id)


> думаешь 100 раз проверка идет одной и той же строки? так
> сказать для гарантии результата?

нет, у него просто для одного P (id) - 100 значений Z по которым он считает, расчет многих Z может разультатов не дать (см [30])... а ему нужен первый получившийся результат... потому многопоточность будет оптимальней последовательности.


> без четкого описания "обработки" автором

ладно, согласен, ждем аффтора... весна покажет кто где гадил :)


 
ANB   (2008-04-17 13:20) [98]


> которая и делает распаралелливание оптимальным решением.
> ..

Распараллеливание на клиенте с хранением всех данных в стриглисте ?
С залезанием в него на каждый чих ?

Для сведения - оракл прекрасно умеет получать данные по HTTP протоколу.
А подводных камней при распараллеливании в нем намного меньше.


 
Palladin ©   (2008-04-17 13:26) [99]


> Распараллеливание на клиенте с хранением всех данных в стриглисте
> ?
> С залезанием в него на каждый чих ?

читать два последних абзаца [83] и мое ессе путь TListView"а до просветления... StringGrid уже давно не рассматривается...


 
ANB   (2008-04-17 13:55) [100]


> Palladin ©   (17.04.08 13:26) [99]
>
> > Распараллеливание на клиенте с хранением всех данных в
> стриглисте
> > ?
> > С залезанием в него на каждый чих ?
>
> читать два последних абзаца [83] и мое ессе путь TListView"а
> до просветления... StringGrid уже давно не рассматривается.
> ..

Обработка 10-20 тысяч записей более 5 минут - это значит проблемы в генофонде. А если укладываться в эти рамки - зачем вообще нужна пользователю визуализация процесса ?


 
Аврам   (2008-04-17 16:40) [101]

афтар тут.
да, больше времени занимает загрузка страницы с интернета, парсинг и анализ проходят быстро....млин все упирается в долгую скачку исходного текта страницы, прост опри разных параметрах запросы получаюстя разные, отсюда и разного размера страница для получения данных с сайта.


 
Аврам   (2008-04-17 16:41) [102]

к сожалению понял это только сейчас...


 
Palladin ©   (2008-04-17 16:42) [103]


> да, больше времени занимает загрузка страницы с интернета,

лично я в этом и не сомневался....


 
sniknik ©   (2008-04-17 16:48) [104]

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

почему и нужно четкое описание, что же всетаки делается.


 
Anatoly Podgoretsky ©   (2008-04-17 16:55) [105]

> Аврам  (17.04.2008 16:40:41)  [101]

Вот и Интернет появился, но это хоть какое то разумное объяснения применения потоков.


 
ANB   (2008-04-17 17:02) [106]


> Аврам   (17.04.08 16:40) [101]
> афтар тут.
> да, больше времени занимает загрузка страницы с интернета,
>  парсинг и анализ проходят быстро....млин все упирается
> в долгую скачку исходного текта страницы, прост опри разных
> параметрах запросы получаюстя разные, отсюда и разного размера
> страница для получения данных с сайта.

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

Мона, конечно, распараллелить выкачку с разными параметрами, но что то мне подсказывает, что загрузить одну большую страничку в одном потоке получится быстрее, чем даже в распараллелке выкачать кучу маленьких. Хотя, возможно, я и не прав. Шустрые качалки этот процесс распараллеливают.


 
Palladin ©   (2008-04-17 17:06) [107]


> Anatoly Podgoretsky ©   (17.04.08 16:55) [105]

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


 
sniknik ©   (2008-04-17 17:11) [108]

> Шустрые качалки этот процесс распараллеливают.
они это делают чтобы обойти ограничение сервера на скорость в одной сессии. т.е. если на сервере ограничивают скачку 100кб-тами, но поддерживают закачку частями, а у вас инет на 1мб, то понятно 10 потоков (до упора своего канала) со скоростью 100кб выкачают файл быстрее чем один на 100.
но вот если переборщить и качать например в 1000 потоков то это уже скорости не прибавит, наоборот понизит, + куча лишнего служебного трафика отожрет.


 
Palladin ©   (2008-04-17 17:16) [109]

о... люди просыпаться начали... вкуривать в ветку... о количестве потоков я осведомился еще в [43] и [44] и не стоит думать что соединение до источника данных идеально... так что понизит или нет еще вопрос, траффик, да, скушает, но если грамотно подойти к вопросу получения информации из интернета, не используя компоненты высокого уровня, а работая на низком уровне сокетов, то можно рвать связь при необходимости...


 
sniknik ©   (2008-04-17 17:17) [110]

> интернет давно появился, я уже запарился всем на это указывать...
его никто (из иначальных в этой ветке) и не игнорировал, но обсуждалось то не помещение части с инетом в поток, а распараллеливание части с "таинственной обработкой данных", которая по логике уже после/вместо/до/пофигу в общем когда но точно <> "закачке данных из инета".


 
ANB   (2008-04-17 17:37) [111]


> Palladin ©   (17.04.08 17:16) [109]
> о... люди просыпаться начали... вкуривать в ветку... о количестве
> потоков я осведомился еще в [43] и [44] и не стоит думать
> что соединение до источника данных идеально... так что понизит
> или нет еще вопрос, траффик, да, скушает, но если грамотно
> подойти к вопросу получения информации из интернета, не
> используя компоненты высокого уровня, а работая на низком
> уровне сокетов
, то можно рвать связь при необходимости..
> .


Боюсь, если автор начнет это реализовывать, то он из форума не вылезет.
Повышение скорости закачки из инета - это отдельная песня.

ЗЫ. Не думаю, что серверу, с которого качают данные, понравится 10 000 одновременных запросов с одного IP.


 
Palladin ©   (2008-04-17 17:39) [112]


> ANB   (17.04.08 17:37) [111]

и где ты взял столько много? процитировать меня процитировал, а вот на ссылаемые посты взглянуть не удосужился... ай ай ай...


 
Аврам   (2008-04-17 18:17) [113]

во блин мужики, я сам офигел. вообще я доделываю начатую работу, только тот программер свалил. Я только щас выяснил что кол-во данных загруженных со страницы - разное при разных запросах к сайту.
Когда обгаваривалось это вначале с заказчиком, то он посчитал что это не имеет значения. чисто случайно проверил. млин!
я и думаю как то странно все получается. оказывается вся загвоздка в этих обращениях к сайту.
получается что надо выносить скачку страницы с сайта в эти отдельные потоки чтоли...


 
ANB   (2008-04-17 18:29) [114]


> Аврам   (17.04.08 18:17) [113]
> во блин мужики, я сам офигел. вообще я доделываю начатую
> работу, только тот программер свалил. Я только щас выяснил
> что кол-во данных загруженных со страницы - разное при разных
> запросах к сайту.
> Когда обгаваривалось это вначале с заказчиком, то он посчитал
> что это не имеет значения. чисто случайно проверил. млин!
>
> я и думаю как то странно все получается. оказывается вся
> загвоздка в этих обращениях к сайту.
> получается что надо выносить скачку страницы с сайта в эти
> отдельные потоки чтоли...

Я бы самым первым попытался сделать запрос или группу их, чтобы минимизировать количество обращений к серверу.
Т.е. одним или несколькими запросами выкачать все на локал, а потом обрабатывать.
И только если время предварительной выкачки все равно будет занимать слишком много времени, начать работу по ускорению этого процесса. В том числе и за счет распараллеливания.
А гос. Palladin вам в этом поможет.


 
Palladin ©   (2008-04-17 18:33) [115]

Я? Я умываю руки и помогать уже не буду. Всем чем мог помог. Написал много букафф. Дело аффтара их переварить или выбросить в помойку.


 
Аврам   (2008-04-17 18:36) [116]

я так понимаю что будет самое то если вынести закачку странциы по запросу.
т.е. выглядеть будет так
типа page :=get(*******);
       if posex(Param_result, page, 1) <> 0 then
        begin
        ....парсинг результатов
           в listview ставиться значения result
           все остальные потоки вырубаются
        end;


 
Palladin ©   (2008-04-17 18:37) [117]

Да, кстати относительно визуализации процесса. Его вообще можно не визуализировать. Я, при написании примера распараллеливания, не ставил это главной задачей, как можно убедится глянув исходники, отказ от визуализации делается очень просто, выбрасыванием к чертям этого Synchronize и переносе исполнения функционала удаления отработанных данных в поток монитор. Только некоторые заказчики любят когда у них там строчечки появляются и исчезают :) типа "компьютер думает"...


 
Palladin ©   (2008-04-17 18:40) [118]


> Аврам   (17.04.08 18:36) [116]

это не поможет, get будет висеть пока не получит все данные по запросу. работать нужно с сокетами на низком уровне, дабы иметь возможность по требованию монитора закрыть соединение и завершится. а здесь я тебе уже не помошник. проси слезно Сергея М., но он не будет таким "лапочкой" как я :)


 
Аврам   (2008-04-17 18:46) [119]

спасибо большое всем за ответы и советы, особенные благодарности Palladin.
могли бы вы мне посоветовать какие нить книги или матерьялы по теме потоков. хотелось бы основательно в этом разобраться чтобы понимать все как вы)


 
Anatoly Podgoretsky ©   (2008-04-17 18:51) [120]

> Palladin  (17.04.2008 18:37:57)  [117]

Заказчика надо любить, я иногда даже грид не отрубаю при проходе по набору данных, пользователь видит, что идет работа, ему приятно, а для меня недорого.


 
Palladin ©   (2008-04-17 19:05) [121]


> Аврам   (17.04.08 18:46) [119]

ну это например....
Грегори Р. Эндрюс
Основы многопоточного, параллельного и распределенного программирования
http://www.ozon.ru/context/detail/id/1372271/

и конечно же Рихтера, Создание эффективных Win32 приложений с учетом специфики 64-разрядной версии Windows


> Anatoly Podgoretsky ©   (17.04.08 18:51) [120]

:) дык, а я о чем...


 
Оригинал   (2008-04-17 19:06) [122]


> Palladin ©   (17.04.08 18:40) [118]
>
> > Аврам   (17.04.08 18:36) [116]
>
> это не поможет, get будет висеть пока не получит все данные
> по запросу.


В Indy TidHTTP позволяет прерывать получение данных с сервера.


 
Palladin ©   (2008-04-17 19:13) [123]


> Оригинал   (17.04.08 19:06) [122]

пример в студию


 
ANB   (2008-04-17 19:16) [124]


> В Indy TidHTTP позволяет прерывать получение данных с сервера.

Это умеет делать даже TWebBrowser


 
Оригинал   (2008-04-17 19:18) [125]


> Palladin ©   (17.04.08 19:13) [123]
>
> > Оригинал   (17.04.08 19:06) [122]
>
> пример в студию


Даже и примера нет необходимости приводить.
Закрывается сокет во время работы, обрабатывается исключение и всё.


 
Оригинал   (2008-04-17 19:44) [126]

Хотя - пожалуйста. Вот пример:

unit Unit1;

interface

uses
 Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
 Dialogs, StdCtrls, ExtCtrls, IdAntiFreezeBase, IdAntiFreeze, IdBaseComponent,
 IdComponent, IdTCPConnection, IdTCPClient, IdHTTP ;

type

 TIH=class(TThread)
 private
   FURL: String;
   FH: TIdHTTP;
 protected
   procedure Execute; override;
 public
   constructor Create(URL: String);
   property H: TIdHTTP read FH write FH;
 end;

 TForm1 = class(TForm)
   Button1: TButton;
   IH: TIdHTTP;
   IdAntiFreeze1: TIdAntiFreeze;
   Timer1: TTimer;
   procedure Timer1Timer(Sender: TObject);
   procedure Button1Click(Sender: TObject);
 private
   { Private declarations }
 public
   { Public declarations }
 end;

var
 Form1: TForm1;
 H: TIH;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
var
 s: String;
begin
 Timer1.Enabled := True;
 H := TIH.Create("http://10.74.1.35/hp/device/this.LCDispatcher?nav=hp.Usage");
end;

procedure TForm1.Timer1Timer(Sender: TObject);
begin
 H.FH.Socket.Close;
 Timer1.Enabled := False;
end;

{ TIH }

constructor TIH.Create(URL: String);
begin
 inherited Create(True);
 FUrl := URL;
 FreeOnTerminate := True;
 Resume;
end;

procedure TIH.Execute;
begin
 FH := TIdHTTP.Create(nil);
 try
   try
     FH.Get(FURL);
   except
     ON E: Exception do MessageBox(0,PChar(E.Message),PChar(E.Message),MB_OK);
   end;
 finally
   FH.Free;
 end;
end;

end.


 
Palladin ©   (2008-04-17 19:51) [127]


>ANB(17.04.08 19:16) [124]

предлагаешь использовать TWebBrowser в качестве транспорта... как все запущено...


>Оригинал (17.04.08 19:44) [126]


а теперь поиграем в 10 отличий исключения в следствии закрытия сокета вручную и другого возникшего из-за реального закрытия в следствие системной ошибки...


 
Anatoly Podgoretsky ©   (2008-04-17 20:30) [128]

> Palladin  (17.04.2008 19:05:01)  [121]

Хе, хе - это исключение, и мне кажется мы говорим о правилах хорошего тона, а не следованию им.
Исключения должны быть осознаными, а правила в данном случае вторичными, поскольку наверх всплывают другие соображения.


 
Anatoly Podgoretsky ©   (2008-04-17 20:32) [129]

> Palladin  (17.04.2008 19:51:07)  [127]

А я посмотрю как это удастся, без внешнего воздействия.


 
Palladin ©   (2008-04-17 21:01) [130]

интересно, а Анатоль знает, что он во сне разговаривает, а его мощнейший разум  проецирует поток сознания прямо на форум... :)


 
Anatoly Podgoretsky ©   (2008-04-17 21:24) [131]

> Palladin  (17.04.2008 21:01:10)  [130]

Это что уже заметно?


 
Anatoly Podgoretsky ©   (2008-04-17 21:25) [132]

> Palladin  (17.04.2008 21:01:10)  [130]

И вообще почему ты решил, что я сплю?


 
ЦУП ©   (2008-04-17 21:59) [133]


> Palladin ©   (17.04.08 19:51) [127]
>Оригинал (17.
> 04.08 19:44) [126]а теперь поиграем в 10 отличий исключения
> в следствии закрытия сокета вручную и другого возникшего
> из-за реального закрытия в следствие системной ошибки...
>


А теперь в качестве домашнего задания подумаем и решим, как это сделать. Маленькая подсказка - создаём в классе метод и...


 
MetalFan ©   (2008-04-18 00:36) [134]


> Оригинал   (17.04.08 19:44) [126]

зря время на написание примера тратили.
можно посмотреть реализацию обработки TIdHttp.ConnectionTimeout
там как раз нечто подобное и сделано.


 
Оригинал   (2008-04-18 01:15) [135]


> MetalFan ©   (18.04.08 00:36) [134]
> > Оригинал   (17.04.08 19:44) [126]зря время на написание
> примера тратили.можно посмотреть реализацию обработки TIdHttp.
> ConnectionTimeoutтам как раз нечто подобное и сделано.


Если ты мне скажешь конкретное название файла, в котором находится реализация - я посмотрю. Ок?


 
Palladin ©   (2008-04-18 10:01) [136]


> ЦУП ©   (17.04.08 21:59) [133]

это ты ребенку своему домашние задания будешь давать

давай, помогай по полной. в каком классе? какой метод? зачем он там нужен? я автору уже помог, теперь, раз ты вызвался, до конца завершай начатое...


 
ANB   (2008-04-18 10:20) [137]


> >ANB(17.04.08 19:16) [124]
>
> предлагаешь использовать TWebBrowser в качестве транспорта.
> .. как все запущено...

Я бы постарался вообще не использовать HTTP в качестве транспорта.

Во всяком случае использование Синхронизе для передачи информации о ходе выполнения в основной поток вместо посылки сообщения - это не меньшая запущенность.

ИМХА :
Потоки надо начинать использовать только если все прочие методы ускорения процесса уже использованы. Далее, перед их использованием неплохо было бы оценить - а действительно ли это даст ускорение, не забывая, что количество процессоров на рабочей станции невелико.
Если  все же принято решение о распараллеливании, то необходимо качественно изучить эту тему и все грабли с ней связанные. А грабли не только в правильном и неправильном использовании Синхронизе.

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


 
Palladin ©   (2008-04-18 10:28) [138]


> Оригинал   (18.04.08 01:15) [135]

IdIOHandlerStack.pas


 
Palladin ©   (2008-04-18 10:50) [139]


> Я бы постарался вообще не использовать HTTP в качестве транспорта.

чем http отличается от не http в плане соединения/отправки/получения/разъединения?


> Во всяком случае использование Синхронизе для передачи информации
> о ходе выполнения в основной поток вместо посылки сообщения
> - это не меньшая запущенность.

к вашему сведению, без Синхронизе никак. если вы считаете что "как", то ткинте меня носом как правильно нужно сделать.

комментировать имху не буду, там и так все ясно, что ветка ниразу не вкурена. хотя при желании, с вашей стороны, могу разобрать каждый тезис. замечу лишь, что приложения бывают не только клиентские, но и серверные. а то "что то", что вам подсказывает про инди лучше не слушайте.


 
Оригинал   (2008-04-18 11:05) [140]


> Palladin ©   (18.04.08 10:01) [136]
>
> > ЦУП ©   (17.04.08 21:59) [133]
>
> это ты ребенку своему домашние задания будешь давать


I>
> Palladin ©   (17.04.08 19:51) [127]
> >Оригинал (17.04.08 19:44) [126]
>
>
> а теперь поиграем в 10 отличий исключения в следствии закрытия
> сокета вручную и другого возникшего из-за реального закрытия
> в следствие системной ошибки...


Обороты сбавь. Хорошо? играй с детьми своими, если они у тебя есть.

Теперь по твоему вопросу как отличить исключение искусственное от любого другого в приведенном примере.
Задачка-то ведь совсем простая. Для этого буквы писать надо?

1. В приведенном поточном классе добавляем метод, например Break
2. Добавляем boolean-флаг в private-секцию, изначально = False.
3. Вместо внешнего обращения к IdHTTP обращаемся к методу, который выставляет флаг и закрывает сокет.
4. При возникновении исключения проверяем флаг.
5. Всё.

Код с минимальными изменениями:

unit Unit1;

interface

uses
 Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
 Dialogs, StdCtrls, ExtCtrls, IdBaseComponent,
 IdComponent, IdTCPConnection, IdTCPClient, IdHTTP ;

type

 TIH=class(TThread)
 private
   FURL: String;
   FH: TIdHTTP;
   FIsBreak: Boolean;
 protected
   procedure Execute; override;
 public
   constructor Create(URL: String);
   procedure Break;
 end;

 TForm1 = class(TForm)
   Button1: TButton;
   Timer1: TTimer;
   procedure Timer1Timer(Sender: TObject);
   procedure Button1Click(Sender: TObject);
 private
   { Private declarations }
 public
   { Public declarations }
 end;

var
 Form1: TForm1;
 H: TIH;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
begin
 H := TIH.Create("http://10.74.1.35/hp/device/this.LCDispatcher?nav=hp.Usage");
 Timer1.Enabled := True;
end;

procedure TForm1.Timer1Timer(Sender: TObject);
begin
 H.Break;
 Timer1.Enabled := False;
end;

{ TIH }

procedure TIH.Break;
begin
 if Assigned(FH) then
 begin
   FIsBreak := True;
   FH.Socket.Close;
 end;
end;

constructor TIH.Create(URL: String);
begin
 inherited Create(True);
 FUrl := URL;
 FreeOnTerminate := True;
 FIsBreak := False;
 Resume;
end;

procedure TIH.Execute;
var
 s: String;
begin
 FH := TIdHTTP.Create(nil);
 try
   try
     FH.Get(FURL);
   except
     ON E: Exception do
     begin
       if FIsBreak then s := " Break connection" else s :="";
       MessageBox(0,PChar(E.Message+s),PChar(E.Message),MB_OK);
     end;
   end;
 finally
   FH.Free;
 end;
end;

end.



 
Оригинал   (2008-04-18 11:12) [141]


> Palladin ©   (18.04.08 10:28) [138]
>
> > Оригинал   (18.04.08 01:15) [135]
>
> IdIOHandlerStack.pas


Нет у меня такого файла-(
(BDS, indy10)


 
Palladin ©   (2008-04-18 11:16) [142]


> Оригинал   (18.04.08 11:05) [140]



> Обороты сбавь. Хорошо? играй с детьми своими, если они у
> тебя есть.

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

по поводу, кода: серьезных претензий нет. теперь много народу прочитает и узнает как прервать get в indy.


 
Palladin ©   (2008-04-18 11:17) [143]


> Оригинал   (18.04.08 11:12) [141]

должен быть. %INDY%\Source\Core\IdIOHandlerStack.pas


 
Оригинал   (2008-04-18 11:39) [144]


> Palladin ©   (18.04.08 11:16) [142]
>
> > Оригинал   (18.04.08 11:05) [140]
>
>
>
> > Обороты сбавь. Хорошо? играй с детьми своими, если они
> у
> > тебя есть.
>
> я чем то тебя оскорбил? тебе что то не нравится? вроде как
> бы не тебе адресовалось. играть с детьми я никому не предлагал,
>  а вот мне тут какое то вдруг домашнее задание давать начали.
>  так может быть обороты то не мне сбавить? а тебе вкурить
> ситуацию. и на личности переходить не будем.


Я ж тебе процитировал твои слова, где ты играть предлагал.
Ну да ладно. Замнем? Зачем разводить здесь ерунду.

У меня в Source в каталоге indy вообще нет подкаталогов. -(


 
Palladin ©   (2008-04-18 11:53) [145]


> Я ж тебе процитировал твои слова, где ты играть предлагал.

процитировал одно, а сказал другое, у меня нет ни слова про игры

я ЦУП"у сказал, что пусть домашние задания дает не мне, а детям своим или чужим, будет куда полезней... мне его домашние задания, с какими то методами класса, никуда не уперлись...


> Замнем?

справедливость восстановлена, замнем


> У меня в Source в каталоге indy вообще нет подкаталогов

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


 procedure DoConnectTimeout(ATimeout: Integer);
 var
   LSleepTime: Integer;
   LInfinite: Boolean;
 begin
   if ATimeout = IdTimeoutDefault then begin
     ATimeout := IdTimeoutInfinite;
   end;
   LInfinite := ATimeout = IdTimeoutInfinite;
   with TIdConnectThread.Create(True) do try
     FBinding := Binding;
     Resume;
     // Sleep
     if TIdAntiFreezeBase.ShouldUse then begin
       LSleepTime := Min(GAntiFreeze.IdleTimeOut, 125);
     end else begin
       LSleepTime := 125;
     end;

     if LInfinite then begin
       ATimeout := LSleepTime + 1;
     end;

     while ATimeout > LSleepTime do begin
       IdGlobal.Sleep(LSleepTime);
       ATimeout := ATimeout - LSleepTime;

       if LInfinite then begin
         ATimeout := LSleepTime + 1;
       end;

       TIdAntiFreezeBase.DoProcess;
       if Terminated then begin
         ATimeout := 0;
         Break;
       end;
     end;
     IdGlobal.Sleep(ATimeout);
     //
     if Terminated then begin
       if FExceptionMessage <> "" then begin
         if FLastSocketError <> 0 then begin
           raise EIdSocketError.CreateError(FLastSocketError, FExceptionMessage);
         end;
         EIdConnectException.Toss(FExceptionMessage);
       end;
     end else begin
       Terminate;
       Close;
       WaitFor;
       EIdConnectTimeout.Toss(RSConnectTimeout);
     end;
   finally Free; end;
 end;

procedure TIdConnectThread.Execute;
begin
 try
   try
     FBinding.Connect;
   except
     on E: EIdSocketError do begin
       if (E.LastError <> Id_WSAEBADF) and (E.LastError <> Id_WSAENOTSOCK) then begin
         raise;
       end;
     end;
   end;
 except
   on E: Exception do begin
     FExceptionMessage := E.Message;
     if E is EIdSocketError then begin
       FLastSocketError := EIdSocketError(E).LastError;
     end;
   end;
 end;
 // Necessary as caller checks this
 Terminate;
end;


то есть, все банально, подключение в другом потоке...


 
ANB   (2008-04-18 15:49) [146]

to Palladin :

Тупейший пример, как передать инфу в основной поток, не используя синхронизацию и критических секций (т.е. без приостановки работы потока).

unit Unit1;

interface

uses
 Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
 StdCtrls;

type
 TMyThread = class(TThread)
 protected
   procedure Execute; override;
 public
   EditHandle : THandle;
 end;

 TForm1 = class(TForm)
   btnStart: TButton;
   btnStop: TButton;
   Edit1: TEdit;
   Edit2: TEdit;
   Edit3: TEdit;
   procedure btnStartClick(Sender: TObject);
   procedure btnStopClick(Sender: TObject);
   procedure Edit1KeyPress(Sender: TObject; var Key: Char);
 private
   { Private declarations }
 public
   { Public declarations }
   T1, T2, T3 : TMyThread;
 end;

var
 Form1: TForm1;

implementation

{$R *.DFM}

procedure TForm1.btnStartClick(Sender: TObject);
begin
 PostMessage(Edit1.Handle, WM_CHAR, 0, 0);
 PostMessage(Edit2.Handle, WM_CHAR, 0, 0);
 PostMessage(Edit3.Handle, WM_CHAR, 0, 0);
 T1 := TMyThread.Create(True);
 T2 := TMyThread.Create(True);
 T3 := TMyThread.Create(True);
 T1.FreeOnTerminate := True;
 T2.FreeOnTerminate := True;
 T3.FreeOnTerminate := True;
 T1.EditHandle := Edit1.Handle;
 T2.EditHandle := Edit2.Handle;
 T3.EditHandle := Edit3.Handle;
 T1.Resume;
 T2.Resume;
 T3.Resume;
end;

{ TMyThread }

procedure TMyThread.Execute;
var i : LongInt;
begin
 for i := 10 to 1000000 do begin
   if Terminated then begin
     PostMessage(EditHandle, WM_CHAR, 1, 0);
     Exit;
   end;
   PostMessage(EditHandle, WM_CHAR, i mod 256, 0);
   Sleep(100);
 end;
end;

procedure TForm1.btnStopClick(Sender: TObject);
begin
 T1.Terminate;
 T2.Terminate;
 T3.Terminate;
end;

procedure TForm1.Edit1KeyPress(Sender: TObject; var Key: Char);
begin
 with Sender as TEdit do begin
   Text := IntToStr(Byte(Key));
 end;
end;

end.



Страницы: 1 2 3 4 вся ветка

Форум: "Начинающим";
Текущий архив: 2008.05.18;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.95 MB
Время: 0.065 c
3-1192531929
NNH
2007-10-16 14:52
2008.05.18
Таблица из Экселя


2-1208603961
lewka-serdceed
2008-04-19 15:19
2008.05.18
как убрать крестик, которым закрывается форма.


6-1172955931
batya18
2007-03-04 00:05
2008.05.18
смена пароля по POP


2-1208239581
Антон Вл.
2008-04-15 10:06
2008.05.18
ehLib


2-1208777886
Rasputin
2008-04-21 15:38
2008.05.18
скопировать изображение окна





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский