![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
потоки
Аврам © (2008-04-15 21:43:00)на форме валяется грид, заполненные данными.
строчек ~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;
т.к. некоторые значения (данные) в гриде очень малы и высчитываются быстро, а быстрое появление результатов для меня важно.
Жду ответов и советов, спасибо!
sniknik (2008-04-17 11:31:00) [61]> сделать входящий массив данных устойчивым и хранящемся в БД, тогда будет саааавсем другой разговор.
саааавсем необязательно хранить данные в БД, чтобы использовать механизмы обработки данных используемые в БД если они вдруг подходят для задачи.
БД то как раз никто и не предлагал.
Anatoly Podgoretsky (2008-04-17 10:05:00) [62]> sniknik (17.04.2008 08:51:21) [81]
По уму и обсуждение.
Palladin (2008-04-17 09:49:00) [63]Итак, начем'с разбор полетов :)
сначала
> Германн © (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:00) [64]Путь 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_p ResultData: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_nDropLines From: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, будет описан вечером, бо мне и свою работу работать надо :)
ЦУП (2008-04-17 09:35:00) [65]
> Аврам (17.04.08 01:11) [78]
А скажи, это принципиально - отображение на форме такой кучи данных?
Если нет, то ты уже сам озвучивал, чт оможно использовать TStringList.
А ещё лучше - связный список. Накладных расходов будет меньше.
sniknik (2008-04-17 08:51:00) [66]> Как минимум автор темы, уже этого хватит.
не хватит. автор темы бесполезен, и даже вреден, для обсуждения если он партизан. и может быть даже забанен, пофигу, тема им начатая будет "жить". пока есть интерес других участников.
> я пришел за помощью на форум "Начинающим".
имхо конечно, но как раз помощь тебя и не интересует, ты просто любишь "парить" людям мозг...
помочь сделать чтото, не зная что, невозможно. а смысл таинственной обработки данных до сих пор не раскрыт.
> Как вы любите говорить для того чтобы поболтать сущ. другие разделы раз уж на то пошло.
видиш ли, твоя ветка настолько не изобилует подробностями, бедна информацией о собственно задаче (метод решения -> перенос в потоки, задачей не является), что попросту провоцирует треп на эту тему. и давно уже она кандидат на перенос в "другие разделы раз уж на то пошло" конкретно в потрепаться. нехватает малости (возможно твоего ответа на вот этот пост, в практикуемом тобой стиле, опять без подробностей что делается).
Аврам (2008-04-17 07:53:00) [67]Как минимум автор темы, уже этого хватит. Пожалуйста лишнего на себя не берите. Я не претендую на статус мастера, и о каких обидах вы говорите, просто хамить здесь не зачем, я пришел за помощью на форум "Начинающим".
Как вы любите говорить для того чтобы поболтать сущ. другие разделы раз уж на то пошло.
С уважением, А.
Германн (2008-04-17 01:47:00) [68]
> Аврам (17.04.08 01:11) [78]
>
> причем тут фильтрация, индексирование и т.д.
> все как делает Palladin как раз то что нужно. никаке бд,
> и тем более поиск мне не нужен.
А ты хто такой? И чего лезешь в дискуссию мастеров?
:)
Не в обиду будь. Ты создал ветку!. Но эта ветка получила иную жизнь.
Аврам (2008-04-17 01:11:00) [69]причем тут фильтрация, индексирование и т.д.
все как делает Palladin как раз то что нужно. никаке бд, и тем более поиск мне не нужен.
Германн (2008-04-17 01:02:00) [70]
> Palladin © (16.04.08 23:29) [74]
>
> в любомслучае я тебе обеспечу производительность работы
> с данными в виртуальном режиме ListView гораздо более производительную
> чем при использовании DataSet'а
>
Тут я скорее поддержу Николая. В большинствеслучаев всё уже разработано для БД. Ну а если я не прав, то ты, Тимур, имеешь все шансы на Нобель. :)
sniknik (2008-04-17 00:30:00) [71]> при чем здесь индексирование? что ты индексировать собрался тут? быстрый поиск значения... какого значения?
намеки на повторяющиеся до 100 раз поиски значения одной записи в других есть в > Аврам (16.04.08 16:07) [34]
без индексов тяжелый поиск будет.
> фильтрация данных... какая еще фильтрация?
обычная. нужно например поиск этой кучи из 100 значений в данных, накладываешь фильтр вместо многочисленных поисков и получаешь нужное сразу.
> чего ты тут фильтровать то собрался?
вообщето ничего... (процесс "обработки" как был тайной так и остался. и, думаю останется)
но, были бы данные, а что из них фильтровать, найдется. данные вроде как есть и немало. 100 строк там у него предполагалось вроде, на поток, и 100 потоков. т.е. 10 000 записей.
Аврам (2008-04-16 23:53:00) [72]
> надо будет завтра у аффтора уточнить происхождение данных
> и критичность упорядоченности при вхождении на обработку.
> ..
данные генеряться на этапе-1. критичность не важна, они и так поступают в определенном порядке и далее идут на обработку.
то о чем мы здесь говорим и о чем эта тема - это этап-2.
Palladin (2008-04-16 23:29:00) [73]в любом случае я тебе обеспечу производительность работы с данными в виртуальном режиме ListView гораздо более производительную чем при использовании DataSet'а
Palladin (2008-04-16 23:23:00) [74]хотя на счет fifo может быть я и неправ... надо будет завтра у аффтора уточнить происхождение данных и критичность упорядоченности при вхождении на обработку...
Palladin (2008-04-16 23:19:00) [75]я тебя умоляю... при чем здесь индексирование? что ты индексировать собрался тут? быстрый поиск значения... какого значения? фильтрация данных... какая еще фильтрация? чего ты тут фильтровать то собрался?
а со своим любимым датасетом ты реально обвешиваешь набор входящих данных для расчета нафик никому ненужным функционалом... пойми, речь идет об fifo...
sniknik (2008-04-16 22:56:00) [76]> но лично я бы заменил на ListView в виртульном режиме...
dataset быстрее и функциональнее. вот как в ListView будеш делать сортировку? (понятно не в самом, раз в виртуальном, а в том динамическом массиве что "под ним")
а индексы поддерживать? нужен быстрый поиск значения? фильтрация данных? и т.д.
dataset готовый компонент по работе с данными. в других же многое будет "велосипедоизобретательством".
Palladin (2008-04-16 22:05:00) [77]
>sniknik©(16.04.08 21:08) [67]
про StringGrid согласен, но лично я бы заменил на ListView в виртульном режиме...
Palladin (2008-04-16 22:05:00) [78]:) тьфу блин, в виртуальном
Аврам (2008-04-16 21:37:00) [79]sniknik, у меня же не БД, анализируемые данные в дальнейшем ненужны.
sniknik (2008-04-16 21:08:00) [80]> не все так безсмысленно, аффтар упомянул о получении данных по http, а это уже совсем другой разговор...
откуда угодно, stringgrid не для обработки данных, отображать, и только часть (!) еще куда ни шло, да и то, гораздо для этого предпочтительнее dbgrig + dataset под данные.