![]() |
| ||
|
|
Новости |
Поиск |
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;
т.к. некоторые значения (данные) в гриде очень малы и высчитываются быстро, а быстрое появление результатов для меня важно.
Жду ответов и советов, спасибо!
Аврам (2008-04-16 20:57:00) [81]спасибо, договорились ))
Palladin (2008-04-16 20:45:00) [82]звиняй, лекция будет уже только завтра... но будет
Аврам (2008-04-16 20:42:00) [83]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:29:00) [84]
>sniknik©(16.04.08 20:08) [61]
не все так безсмысленно, аффтар упомянул о получении данных по http, а это уже совсем другой разговор...
Аврам (2008-04-16 20:25:00) [85]sniknik, не тебе судить что лучше, если хочешь помочь, то помагай - буду благодарен, а говорить о том чего не знаешь - не стоит. Думаю ты меня понял. Чтобы подобные советы "нанять программиста" и нафига доп. комп. тут больше не обсуждались разъесню немного. Данные будут считыватья в течении 5-8 часов, и нужно постоянно наблюдать за происходящим. (получение результатов). Нашелся никем не используемый компьютер. вот его под это дело и дали. К этйо теме кол-во ком. и его мощность никак не относиться.
Спасибо всем за ответы и за советы.
Учусь. С уважением, А.
sniknik (2008-04-16 20:08:00) [86]афигеть... дополнительный компьютер под задачу которая считает данные в stringgrid-е, и тормозит изза потоков... лучше бы программиста наняли.
Palladin (2008-04-16 19:54:00) [87]
> Аврам (16.04.08 19:53) [59]
куда хочешь туда и вставляй...
Аврам (2008-04-16 19:53:00) [88]Palladin, код который ты привел нужно вставлять в основном приложении или в отдельно созданном уните - потоке ?
Palladin (2008-04-16 19:30:00) [89]
> вроде бы нигде не ошибся...
все таки ошибся... пропустил Inc(i) в Function _WaitForThreads:Boolean;
Аврам (2008-04-16 19:27:00) [90]вах...спасибо! щас буду разбираться...))
Palladin (2008-04-16 18:38:00) [91]
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'а
вроде бы нигде не ошибся...
Dennis I. Komarov (2008-04-16 17:38:00) [92]> [51] Аврам (16.04.08 17:26)
50 постов спустя появляются все новые и новые исходные :(
Palladin (2008-04-16 17:37:00) [93]
> Аврам (16.04.08 17:35) [53]
есть, но это аварийный выход, в случае если по хорошему поток завершатся не хочет, и это чревато неприятностями. от банальной утечки памяти, до блокирования некоторых системных ресурсов...
хорошо раз готов, жди...
Аврам (2008-04-16 17:35:00) [94]готов.
я предпологал что есть возможность послать группе потоков принудительный выход, ьез использования If Terminated Then Exit;
Palladin (2008-04-16 17:33:00) [95]
> Аврам (16.04.08 17:26) [51]
я не прошу тебя выкладывать тексты... раз ты определить распределение тяжести по алгоритму не в состоянии, то придется в нем на каждый чих с данными (практически через каждую строчку) вставлять следующее
If Terminated Then Exit; , а так же окаймить метод execute скобками try finally end, для корректного освобождения взятых в процессе ресурсов при exit
ты готов к этому?
Аврам (2008-04-16 17:26:00) [96]к сожалению я не все исходные тексты могу выкладывать.
Аврам (2008-04-16 17:25:00) [97]забыл сказать еще одну важную весчь,в одном месте еще есть загрузка некоторых данных с интернета (есть сервер с данными, которые постоянно меняются).
это выглядит так page := get(***);в page загружается страница и беруться оттуда некоторые данные парсингом.
Dennis I. Komarov (2008-04-16 17:22:00) [98]> [48] Palladin © (16.04.08 17:21)
Партизаны не сдаются!!!
Palladin (2008-04-16 17:21:00) [99]я просто хочу выяснить, на сколько тяжел весь алгоритм в целом и есть ли в нем контрастно тяжеленные места?
Palladin (2008-04-16 17:16:00) [100]
> Аврам (16.04.08 17:14) [46]
циклы for to do, while do, repeat until используются в вычислениях или одна только формула?