Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: Общие вопросы > Динамическое создание потоков TThread


Автор: ppc 1.7.2007, 17:57
Добрый день, мастера!

Подскажите, пожалуйста. Нужно создать 100 потоков класса TThread, причем на DoWork каждый поток должен выполнять одно и тоже действие. Конечно можно сделать руками, но сами понимаете..., наверное есть какой-то другой способ. Спасибо

Автор: skyboy 1.7.2007, 18:04
Цитата(ppc @  1.7.2007,  16:57 Найти цитируемый пост)
Конечно можно сделать руками

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

Автор: ppc 1.7.2007, 18:12
Вот, нужно автоматизировать



Код

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

TMyThread2 = class(TThread)
   private
     { Private declarations }
   protected
     procedure DoWork;
     procedure Execute; override;
   end;
TMyThread3 = class(TThread)
   private
     { Private declarations }
   protected
     procedure DoWork;
     procedure Execute; override;
   end;
TMyThread4 = class(TThread)
   private
     { Private declarations }
   protected
     procedure DoWork;
     procedure Execute; override;
   end;

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

TMyThread6 = class(TThread)
   private
     { Private declarations }
   protected
     procedure DoWork;
     procedure Execute; override;
   end;
var
  Form1: TForm1;
  T1:TMyThread1;
  T2:TMyThread2;
    T3:TMyThread3;
  T4:TMyThread4;
    T5:TMyThread5;
  T6:TMyThread6;

implementation

{$R *.dfm}

procedure TMyThread1.Execute;
 begin
   while not Terminated do
     Synchronize(DoWork);
end;

procedure TMyThread2.Execute;
 begin
   while not Terminated do
     Synchronize(DoWork);
end;

procedure TMyThread3.Execute;
 begin
   while not Terminated do
     Synchronize(DoWork);
end;

procedure TMyThread4.Execute;
 begin
   while not Terminated do
     Synchronize(DoWork);
end;

procedure TMyThread5.Execute;
 begin
   while not Terminated do
     Synchronize(DoWork);
end;

procedure TMyThread6.Execute;
 begin
   while not Terminated do
     Synchronize(DoWork);
end;


procedure TMyThread1.DoWork;
 begin
  Application.ProcessMessages;
Form1.WebBrowser1.Navigate('http://google.com/');
end;

procedure TMyThread2.DoWork;
 begin
  Application.ProcessMessages;
Form1.WebBrowser2.Navigate('http://aport.ru/');
end;

procedure TMyThread3.DoWork;
 begin
  Application.ProcessMessages;
Form1.WebBrowser3.Navigate('http://rambler.ru/');
end;

procedure TMyThread4.DoWork;
 begin
  Application.ProcessMessages;
Form1.WebBrowser4.Navigate('http://yandex.ru/');
end;

procedure TMyThread5.DoWork;
 begin
  Application.ProcessMessages;
Form1.WebBrowser5.Navigate('http://vingrad.ru/');
end;

procedure TMyThread6.DoWork;
 begin
 Application.ProcessMessages;
Form1.WebBrowser6.Navigate('http://yahoo.com/');
end;



procedure TForm1.Button1Click(Sender: TObject);
begin
T1.DoWork;
T2.DoWork;
T3.DoWork;
T4.DoWork;
T5.DoWork;
T6.DoWork;
end;


Автор: skyboy 1.7.2007, 18:44
тэк. 
номер раз:
ты НЕ должен вызывать ни метод Execute, ни, тем более, собственноручно описанный doWork. Надо: 
  • либо создавать поток с паарметром createSuspended = false(тогда поток сразу будет запущен - будет вызыван метод объекта Execute)
  • либо создавать поток приостановленным(createSuspended = true) и, затем, "размораживать" поток
номер два:
где создание объектов? ты объявил переменные(
Код

var
  Form1: TForm1;
  T1:TMyThread1;
  T2:TMyThread2;
    T3:TMyThread3;
  T4:TMyThread4;
    T5:TMyThread5;
  T6:TMyThread6;
)
а создавать объекты кто будет? и что, у тебя при такой работе не было Access Violation?! Не верю smile
номер три: раз создал "собственный" метод, то почему не создал собственное поле, хранящее то, что у тебя от потока к потоку отличается - WebBrowser?!
Код

interface 
{....}
TMyThread  = class(TThread)
protected 
 _url: string;
 procedure doWork; 
 function getURL: string;
 procedure writeURL(AValue: string);
public
 property url: string read getURL write setURL;
 WebBrowser: TWebBroswer;
 procedure Execute; override;
end;
{...}
var 
 Form1: TForm1;
 thread1,thread2,thread3,thread4: TMyThread;
{...}
implementation
function getURL: string;
begin
 Result:= 'http://' + _url;
end;

procedure setURL(AValue: string);
begin
{всякие проверки на валидность URL}
_url:= AValue;
end;

procedure TMyThread.doWork;
begin
 Application.ProcessMessages;
 if Assigned(Self.WebBrowser)  AND (_url <> '')
  then // если у нас есть адрес и компонент, которому надо этот адрес передать
   WebBrowser.Navigate(url) 
  else // либо адрес не дали, либо кому передавать - не сказали...
   raise EInvalidOperation.Create('Нельзя передавать пустые адреса неуказанным компонентам! Ай-ай-ай!');
end;

procedure TMyThread.Execute;
begin
 Synchronize(Self.DoWork);
end;

{...}
procedure TForm1.Button1Click(Sender: TObject);
begin
thread1:= TMyThread.Create(true); // создаем поток приостановленным
thread1.WebBrowser:= Self.WebBrowser1; // фактически записываем в свойство WEBBrowser объекта - потока ссылку на Form1.WebBrowser1
thread1.url:= 'forum.vingrad.ru'; // записываем соотвествующий URL
thread1.resume(); // снимаем поток с ручника

thread2:= TMyThread.Create(true); // создаем поток приостановленным
thread2.WebBrowser:= Self.WebBrowser2; // фактически записываем в свойство WEBBrowser объекта - потока ссылку на Form1.WebBrowser2
thread2.url:= 'google.com'; // записываем соотвествующий URL
thread2.resume(); // снимаем поток с ручника

thread3:= TMyThread.Create(true); // создаем поток приостановленным
thread3.WebBrowser:= Self.WebBrowser3; // фактически записываем в свойство WEBBrowser объекта - потока ссылку на Form1.WebBrowser3
thread3.url:= 'yahoo.com.ua'; // записываем соотвествующий URL
thread3.resume(); // снимаем поток с ручника
end;

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

Добавлено через 58 секунд
номер четыре: найди над формой быстрого ввода ответа(справа вверху) кнопку "Код". И обрамляй свой код спецтегами при помощи этой кнопки - и полезно, и приятно  smile 

Автор: ppc 1.7.2007, 22:58
Код

unit Unit1;

interface

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

type
  TForm1 = class(TForm)
    WebBrowser1: TWebBrowser;
    WebBrowser2: TWebBrowser;
    WebBrowser3: TWebBrowser;
    WebBrowser4: TWebBrowser;
    WebBrowser5: TWebBrowser;
    WebBrowser6: TWebBrowser;
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;
TMyThread1 = class(TThread)
   private
     { Private declarations }
   protected
     procedure DoWork;
     procedure Execute; override;
   end;

TMyThread2 = class(TThread)
   private
     { Private declarations }
   protected
     procedure DoWork;
     procedure Execute; override;
   end;
TMyThread3 = class(TThread)
   private
     { Private declarations }
   protected
     procedure DoWork;
     procedure Execute; override;
   end;
TMyThread4 = class(TThread)
   private
     { Private declarations }
   protected
     procedure DoWork;
     procedure Execute; override;
   end;

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

TMyThread6 = class(TThread)
   private
     { Private declarations }
   protected
     procedure DoWork;
     procedure Execute; override;
   end;
var
  Form1: TForm1;
  T1:TMyThread1;
  T2:TMyThread2;
    T3:TMyThread3;
  T4:TMyThread4;
    T5:TMyThread5;
  T6:TMyThread6;

implementation

{$R *.dfm}

procedure TMyThread1.Execute;
 begin
   while not Terminated do
     Synchronize(DoWork);
end;

procedure TMyThread2.Execute;
 begin
   while not Terminated do
     Synchronize(DoWork);
end;

procedure TMyThread3.Execute;
 begin
   while not Terminated do
     Synchronize(DoWork);
end;

procedure TMyThread4.Execute;
 begin
   while not Terminated do
     Synchronize(DoWork);
end;

procedure TMyThread5.Execute;
 begin
   while not Terminated do
     Synchronize(DoWork);
end;

procedure TMyThread6.Execute;
 begin
   while not Terminated do
     Synchronize(DoWork);
end;


procedure TMyThread1.DoWork;
 begin
  Application.ProcessMessages;
Form1.WebBrowser1.Navigate('http://google.com/');
end;

procedure TMyThread2.DoWork;
 begin
  Application.ProcessMessages;
Form1.WebBrowser2.Navigate('http://aport.ru/');
end;

procedure TMyThread3.DoWork;
 begin
  Application.ProcessMessages;
Form1.WebBrowser3.Navigate('http://rambler.ru/');
end;

procedure TMyThread4.DoWork;
 begin
  Application.ProcessMessages;
Form1.WebBrowser4.Navigate('http://yandex.ru/');
end;

procedure TMyThread5.DoWork;
 begin
  Application.ProcessMessages;
Form1.WebBrowser5.Navigate('http://vingrad.ru/');
end;

procedure TMyThread6.DoWork;
 begin
 Application.ProcessMessages;
Form1.WebBrowser6.Navigate('http://yahoo.com/');
end;



procedure TForm1.Button1Click(Sender: TObject);
begin
T1.DoWork;
T2.DoWork;
T3.DoWork;
T4.DoWork;
T5.DoWork;
T6.DoWork;
end;

end.


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


Точнее, мне нужно както это оптимизировать

Код

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

TMyThread2 = class(TThread)
   private
     { Private declarations }
   protected
     procedure DoWork;
     procedure Execute; override;
   end;
TMyThread3 = class(TThread)
   private
     { Private declarations }
   protected
     procedure DoWork;
     procedure Execute; override;
   end;
TMyThread4 = class(TThread)
   private
     { Private declarations }
   protected
     procedure DoWork;
     procedure Execute; override;
   end;

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

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



чтоб можно было поставить в цикл и создавать неограниченное количество потоков

Автор: skyboy 1.7.2007, 23:45
Цитата(ppc @  1.7.2007,  21:58 Найти цитируемый пост)
чесно говоря я не понял, что ты сделал

что сам-то сделал - понял? ты объявил(собираешься объявить) 100 классов, единственный различный метод которых отличается исключительно данными, которые можно было спокойно вынести в поле объекта и использовать один класс с одним описанием для всех ста переменных-потоков, а не описывать сто TMyThread... которые отличаются только тем, с каким WEBBrowser'ом работают.
Кроме того, совершенно неясно, как ты, вызывая метод DoWork напрямую у несозданного(по крайней мере, по коду не видно создания) объекта не получаешь Access violation.
Цитата(ppc @  1.7.2007,  21:58 Найти цитируемый пост)
Знаю, что нужно использовать цикл For

надо хороший учебник использовать. И внимательно читать.
Что такое класс знаешь? А метод? А объект? 

Автор: Romikgy 1.7.2007, 23:52
У тя этот код компилится?
или работает? (хотя и про компилится у мя увериности нет ....
и зачем создавать 6 классов , если они делают одно и тоже?
плюс по логике понял 

Цитата(ppc @  1.7.2007,  21:58 Найти цитируемый пост)
T1.DoWork;
T2.DoWork;
T3.DoWork;
T4.DoWork;
T5.DoWork;
T6.DoWork;

что это вызывается в основном потоке , тогда зачем вообще было потоки юзать ?
skyboy, те пример привел , что еще мудрить то надо?

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