![]() |
| ||
|
|
Новости |
Поиск |
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;
т.к. некоторые значения (данные) в гриде очень малы и высчитываются быстро, а быстрое появление результатов для меня важно.
Жду ответов и советов, спасибо!
ANB (2008-04-18 15:49:00) [1]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.
Palladin (2008-04-18 11:53:00) [2]
> Я ж тебе процитировал твои слова, где ты играть предлагал.
процитировал одно, а сказал другое, у меня нет ни слова про игры
я ЦУП'у сказал, что пусть домашние задания дает не мне, а детям своим или чужим, будет куда полезней... мне его домашние задания, с какими то методами класса, никуда не уперлись...
> Замнем?
справедливость восстановлена, замнем
> У меня в 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;
то есть, все банально, подключение в другом потоке...
Оригинал (2008-04-18 11:39:00) [3]
> Palladin © (18.04.08 11:16) [142]
>
> > Оригинал (18.04.08 11:05) [140]
>
>
>
> > Обороты сбавь. Хорошо? играй с детьми своими, если они
> у
> > тебя есть.
>
> я чем то тебя оскорбил? тебе что то не нравится? вроде как
> бы не тебе адресовалось. играть с детьми я никому не предлагал,
> а вот мне тут какое то вдруг домашнее задание давать начали.
> так может быть обороты то не мне сбавить? а тебе вкурить
> ситуацию. и на личности переходить не будем.
Я ж тебе процитировал твои слова, где ты играть предлагал.
Ну да ладно. Замнем? Зачем разводить здесь ерунду.
У меня в Source в каталоге indy вообще нет подкаталогов. -(
Palladin (2008-04-18 11:17:00) [4]
> Оригинал (18.04.08 11:12) [141]
должен быть. %INDY%\Source\Core\IdIOHandlerStack.pas
Palladin (2008-04-18 11:16:00) [5]
> Оригинал (18.04.08 11:05) [140]
> Обороты сбавь. Хорошо? играй с детьми своими, если они у
> тебя есть.
я чем то тебя оскорбил? тебе что то не нравится? вроде как бы не тебе адресовалось. играть с детьми я никому не предлагал, а вот мне тут какое то вдруг домашнее задание давать начали. так может быть обороты то не мне сбавить? а тебе вкурить ситуацию. и на личности переходить не будем.
по поводу, кода: серьезных претензий нет. теперь много народу прочитает и узнает как прервать get в indy.
Оригинал (2008-04-18 11:12:00) [6]
> Palladin © (18.04.08 10:28) [138]
>
> > Оригинал (18.04.08 01:15) [135]
>
> IdIOHandlerStack.pas
Нет у меня такого файла-(
(BDS, indy10)
Оригинал (2008-04-18 11:05:00) [7]
> 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.
Palladin (2008-04-18 10:50:00) [8]
> Я бы постарался вообще не использовать HTTP в качестве транспорта.
чем http отличается от не http в плане соединения/отправки/получения/разъединения?
> Во всяком случае использование Синхронизе для передачи информации
> о ходе выполнения в основной поток вместо посылки сообщения
> - это не меньшая запущенность.
к вашему сведению, без Синхронизе никак. если вы считаете что "как", то ткинте меня носом как правильно нужно сделать.
комментировать имху не буду, там и так все ясно, что ветка ниразу не вкурена. хотя при желании, с вашей стороны, могу разобрать каждый тезис. замечу лишь, что приложения бывают не только клиентские, но и серверные. а то "что то", что вам подсказывает про инди лучше не слушайте.
Palladin (2008-04-18 10:28:00) [9]
> Оригинал (18.04.08 01:15) [135]
IdIOHandlerStack.pas
ANB (2008-04-18 10:20:00) [10]
> >ANB(17.04.08 19:16) [124]
>
> предлагаешь использовать TWebBrowser в качестве транспорта.
> .. как все запущено...
Я бы постарался вообще не использовать HTTP в качестве транспорта.
Во всяком случае использование Синхронизе для передачи информации о ходе выполнения в основной поток вместо посылки сообщения - это не меньшая запущенность.
ИМХА :
Потоки надо начинать использовать только если все прочие методы ускорения процесса уже использованы. Далее, перед их использованием неплохо было бы оценить - а действительно ли это даст ускорение, не забывая, что количество процессоров на рабочей станции невелико.
Если все же принято решение о распараллеливании, то необходимо качественно изучить эту тему и все грабли с ней связанные. А грабли не только в правильном и неправильном использовании Синхронизе.
На практике я практически не встречал необходимости использовать доп.потоки. Обычно это проблема начинающих - виснет форма, повешу доп. поток. При этом не думая переносится код из основного потока в дополнительный.
Единственно, где я не вижу возражений против использования доп. потоков - это выкачка из инета. Однако этой темой я не занимался. Но что то подсказывает мне, что индевая библиотека умеет работать асинхронно, соответственно и здесь потоки не нужны тогда.
Palladin (2008-04-18 10:01:00) [11]
> ЦУП © (17.04.08 21:59) [133]
это ты ребенку своему домашние задания будешь давать
давай, помогай по полной. в каком классе? какой метод? зачем он там нужен? я автору уже помог, теперь, раз ты вызвался, до конца завершай начатое...
Оригинал (2008-04-18 01:15:00) [12]
> MetalFan © (18.04.08 00:36) [134]
> > Оригинал (17.04.08 19:44) [126]зря время на написание
> примера тратили.можно посмотреть реализацию обработки TIdHttp.
> ConnectionTimeoutтам как раз нечто подобное и сделано.
Если ты мне скажешь конкретное название файла, в котором находится реализация - я посмотрю. Ок?
MetalFan (2008-04-18 00:36:00) [13]
> Оригинал (17.04.08 19:44) [126]
зря время на написание примера тратили.
можно посмотреть реализацию обработки TIdHttp.ConnectionTimeout
там как раз нечто подобное и сделано.
ЦУП (2008-04-17 21:59:00) [14]
> Palladin © (17.04.08 19:51) [127]
>Оригинал (17.
> 04.08 19:44) [126]а теперь поиграем в 10 отличий исключения
> в следствии закрытия сокета вручную и другого возникшего
> из-за реального закрытия в следствие системной ошибки...
>
А теперь в качестве домашнего задания подумаем и решим, как это сделать. Маленькая подсказка - создаём в классе метод и...
Anatoly Podgoretsky (2008-04-17 21:25:00) [15]> Palladin (17.04.2008 21:01:10) [130]
И вообще почему ты решил, что я сплю?
Anatoly Podgoretsky (2008-04-17 21:24:00) [16]> Palladin (17.04.2008 21:01:10) [130]
Это что уже заметно?
Palladin (2008-04-17 21:01:00) [17]интересно, а Анатоль знает, что он во сне разговаривает, а его мощнейший разум проецирует поток сознания прямо на форум... :)
Anatoly Podgoretsky (2008-04-17 20:32:00) [18]> Palladin (17.04.2008 19:51:07) [127]
А я посмотрю как это удастся, без внешнего воздействия.
Anatoly Podgoretsky (2008-04-17 20:30:00) [19]> Palladin (17.04.2008 19:05:01) [121]
Хе, хе - это исключение, и мне кажется мы говорим о правилах хорошего тона, а не следованию им.
Исключения должны быть осознаными, а правила в данном случае вторичными, поскольку наверх всплывают другие соображения.
Palladin (2008-04-17 19:51:00) [20]
>ANB(17.04.08 19:16) [124]
предлагаешь использовать TWebBrowser в качестве транспорта... как все запущено...
>Оригинал (17.04.08 19:44) [126]
а теперь поиграем в 10 отличий исключения в следствии закрытия сокета вручную и другого возникшего из-за реального закрытия в следствие системной ошибки...