Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: Сети > Многопоточность


Автор: SymplyFying 27.5.2006, 22:05
Здравствуйте.
Есть код:
Код

unit Unit1;

interface

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

type
  TMyThread = class(TThread)
  private
    { Private declarations }
  protected
    procedure Execute; override;
  end;

type
  TForm1 = class(TForm)
    Edit1: TEdit;
    Button1: TButton;
    Memo1: TMemo;
    procedure Button1Click(Sender: TObject);
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
   Form1: TForm1;
   wsdata: TWSAData;
   adr: sockaddr_in;
   temp: string;
implementation


{$R *.dfm}



procedure TForm1.Button1Click(Sender: TObject);
var
host:string;
begin
temp                :=edit1.text;
host                :=resolve('host.ru');
adr.sin_addr.s_addr :=inet_addr(pchar(host));
adr.sin_family      :=AF_INET;
adr.sin_port        :=htons(80);
TMyThread.Create(false);
end;

procedure TMyThread.Execute;
var
sock,i: integer;
req: string;
ans: string;
begin
Sock:=Socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
if sock =-1 then Exit;
if connect(sock,adr,sizeof(adr))<>0 then begin
CloseSocket(Sock);
exit;
end;
req:='GET /'+temp+' HTTP/1.1';
SendString(sock, req);
ans:=ans+ReadString(Sock);
CloseSocket(Sock);
Memo1.Lines.Add(ans);
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
wsaStartup(MAKEWORD(1,1), wsData);
end;

end.


Как мне сделать многопоточность на основе данного кода?
И как в поток передавать параметры, если у меня переменная temp будет заменена stringlistom? Т.е. чтобы каждый новый поток получал за место переменной temp следующую строку хранящуюся в stringlist?
За ранее спасибо за ответы. 

Автор: Демо 28.5.2006, 09:34
SymplyFying,

Для начала желательно вообще что-нибудь о потоках почитать.
Например, это - http://www.delphimaster.ru/articles/panov/index.html
Это - http://forum.vingrad.ru/index.php?showtopic=60076 

Автор: SymplyFying 28.5.2006, 11:03
Демо, спасибо что ответил smile
Я читал это уже, но к сожалению не понял smile Вот и прошу помощи у Вас. 

Автор: Демо 28.5.2006, 11:12
SymplyFying
Для передачи параметров потоку применяется либо переопределение конструктора, либо добавляются методы/свойства - как и в любом другом классе.

Примеров в сети вообще полно, да и в DElphi\demo тоже, но приведу простой пример все равно:

Код

 TMyThread = class(TThread)    
  private    
    FParam: String;
  protected    
    procedure Execute; override;    
  public
    constructor Create(const Param: String);
  end;

...

constructor TMyThread.Create(const Param: String);
begin
  inherited Create(True);
  FParam := Param;
  FreeOnTerminate := True;
  Resume;
end;




Переопределение конструктора применяется и в примерах в первой из приведенных ссылок. Так что все-таки рекомендую сначала прочитать статью. 

Автор: SymplyFying 28.5.2006, 11:27
Что-то типа:
Код


unit Unit1;
interface
uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls,Winsock,SockFuncs;
type
  TMyThread = class(TThread)
  private
    { Private declarations }
  protected
    procedure Execute; override;
  end;
type
  TForm1 = class(TForm)
    Edit1: TEdit;
    Button1: TButton;
    Memo1: TMemo;
    procedure Button1Click(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure create;
  private
    { Private declarations }
  public
    { Public declarations }
  end;
var
   Form1: TForm1;
   wsdata: TWSAData;
   adr: sockaddr_in;
   temp: string;
   list: tstringlist;
implementation
{$R *.dfm}

procedure TForm1.Create;
begin
If List.Count=0 then exit;
with TMyThread.Create(True) do
    begin
      FreeOnTerminate:=True;
      temp:=List.Strings[0];
      Resume;
    end;
List.Delete(0);
end;

procedure TForm1.Button1Click(Sender: TObject);
var
host:string;
begin
host                :=resolve('host.ru');
adr.sin_addr.s_addr :=inet_addr(pchar(host));
adr.sin_family      :=AF_INET;
adr.sin_port        :=htons(80);
for i:=1 to 10 do // это типа делаем 10 потоков
create;
end;

procedure TMyThread.Execute;
var
sock,i: integer;
req: string;
ans: string;
begin
Sock:=Socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
if sock =-1 then Exit;
if connect(sock,adr,sizeof(adr))<>0 then begin
CloseSocket(Sock);
exit;
end;
req:='GET /'+temp+' HTTP/1.1';
SendString(sock, req);
ans:=ans+ReadString(Sock);
CloseSocket(Sock);
Memo1.Lines.Add(ans);
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
wsaStartup(MAKEWORD(1,1), wsData);
list:=tstringlist.create;
end;
end

Правильно оформлен код или нет?

Добавлено @ 11:30 
Демо, спасибо за быстрые ответы smile
Твой второй пост не видел когда писал ответ и сам написал код smile Не мог бы ты сказать всё ли там правильно?

Цитата(Демо @  28.5.2006,  11:12 Найти цитируемый пост)
Так что все-таки рекомендую сначала прочитать статью.  

Читал. Может просто не вник. Счас ещё раз перечитаю. 

Автор: Aleksiem 31.5.2006, 00:21
Для начала по-моему не один объект не уничтожается.
В конце процедуры TMyThread.Execute вставь Terminate;
В конце программы StringList тоже уничтожь. Опять же непонятные функции SendString и ReadString (по-моему в winsock они не описаны), но я так понимаю это запись и чтение данных в сокет. Но на счёт многопоточности примерно всё так, хотя можно было и попонятнее оформить. 

Автор: SymplyFying 31.5.2006, 01:03
Цитата(Aleksiem @  31.5.2006,  00:21 Найти цитируемый пост)
Для начала по-моему не один объект не уничтожается.

=) Потоки не уничтожаються.
Стринглист уничтожаеться, просто здесь забыл.
Цитата(Aleksiem @  31.5.2006,  00:21 Найти цитируемый пост)
Опять же непонятные функции SendString и ReadString (по-моему в winsock они не описаны)

Они точно работают.
Цитата(Aleksiem @  31.5.2006,  00:21 Найти цитируемый пост)
Но на счёт многопоточности примерно всё так

А вот такой вопрос возник:
Код

for i:=1 to 10 do // это типа делаем 10 потоков
create;

Это получается я делаю 10 потоков для первых 10 строчек? А если надо весь StringList обработать, где, например, около 5000 строк - это надо 5000 потоков создавать? Или нет?
Можно как нибудь оформить, чтобы можно было вводить любое кол-во паралельных потоков, и чтобы при этом обрабатывался весь файл.(сильно не пинайте если что не так сформулировал ;) )
Цитата(Aleksiem @  31.5.2006,  00:21 Найти цитируемый пост)
хотя можно было и попонятнее оформить.  

Как? Буду очень признателен за пример ;)

Добавлено @ 01:04 
Ну вот, блин. smile Хотел "+" поставить Демо и Aleksiem. А низя. 

Автор: Демо 31.5.2006, 08:51
Цитата(SymplyFying @  31.5.2006,  01:03 Найти цитируемый пост)
Можно как нибудь оформить, чтобы можно было вводить любое кол-во паралельных потоков, 


http://forum.sources.ru/index.php?showtopic=120033&view=showall&hl=idhttp 

Автор: N1k 31.5.2006, 16:04
чтоб весь список обработался...
Код

...
  TMyThread = class(TThread)
  private
    FTmp:string
    { Private declarations }
  protected
    procedure Execute; override;
  public
    property Str:string read FTmp write FTmp
  end;
...
procedure TMyThread.Execute;
var
sock,i: integer;
req: string;
ans: string;
adr: sockaddr_in;
host:string;
begin
host                :=resolve('host.ru');
adr.sin_addr.s_addr :=inet_addr(pchar(host));
adr.sin_family      :=AF_INET;
adr.sin_port        :=htons(80);
Sock:=Socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
if sock =-1 then Exit;
if connect(sock,adr,sizeof(adr))<>0 then begin
CloseSocket(Sock);
exit;
end;
req:='GET /'+FTmp+' HTTP/1.1';
SendString(sock, req);
ans:=ans+ReadString(Sock);
CloseSocket(Sock);
Memo1.Lines.Add(ans);
end;
...
procedure ThreadTerminate(Sender: TObject);
...
procedure TForm1.Create;// я б не стал так называть
begin
If List.Count=0 then exit;
with TMyThread.Create(True) do
    begin
      FreeOnTerminate:=True;
      OnTerminate:=ThreadTerminate;
      Str:=List.Strings[0];
      Resume;
    end;
List.Delete(0);
end;
...
procedure TForm1.ThreadTerminate(Sender: TObject);
begin
create;
end;


Приблизительно так, хотя не все ошибки исправил... 

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)