Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 2004.04.11;
Скачать: [xml.tar.bz2];

Вниз

Вопрос по TThread   Найти похожие ветки 

 
Кипяток   (2004-03-25 14:43) [0]

Здрасти господа мастера.
Вопрос такой возможно ли использовать TThread в консольном приложении.


 
Юрий Зотов ©   (2004-03-25 14:47) [1]

Можно.


 
Кипяток   (2004-03-25 14:48) [2]

для примера

program console;
{$APPTYPE CONSOLE}
uses SysUtils, Classes;
type
  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;
var Form1: TForm1;
    T1   : TMyThread1;
    T2   : TMyThread2;
procedure TMyThread1.Execute;
begin
  while not Terminated do
    Synchronize(DoWork);
end;
procedure TMyThread2.Execute;
begin
  while not Terminated do
    Synchronize(DoWork);
end;
procedure TMyThread1.DoWork;
begin
  Writeln("Thread1");
end;
procedure TMyThread2.DoWork;
begin
   Writeln("Thread2");
end;
begin
T1 := TMyThread1.Create(False);
T2 := TMyThread2.Create(False);
T1.Execute;
T2.Execute;
end.



работает только первый
точнее в консоли пишется
только Thread1

укажите на ошибку


 
Fay ©   (2004-03-25 14:52) [3]

Простите за нескромный вопрос, но зачем именно TThread?!


 
Кипяток   (2004-03-25 14:54) [4]

это я для примера написал
мне надо(точнее заказчику), чтобы два процесса крутились одновременно независимо друг от друга, может другой путь посоветуете. Буду очень признателен.


 
Digitman ©   (2004-03-25 14:59) [5]


> чтобы два процесса крутились одновременно


два процесса или два трэда ? разные ж вещи ..


 
KSergey ©   (2004-03-25 15:02) [6]

Просто запусти вда EXE - вот и все дела ;)


 
Кипяток   (2004-03-25 15:04) [7]

2Digitman я думал что одно и тоже, а в чем разница

Вообщем давайте не будем обсуждать постановку задачи, может поможете советом по существу (см. исходник)


 
Digitman ©   (2004-03-25 15:06) [8]

begin
T1 := TMyThread1.Create(False);
T2 := TMyThread2.Create(False);
T1.Free;
T2.Free;
end.


 
Кипяток   (2004-03-25 15:06) [9]

2KSergey два еще не получится у обоих задач общие переменные.


 
Defunct ©   (2004-03-25 15:08) [10]

Synchronize(DoWork);
T1.Execute;
T2.Execute;


Это зачем?
И зачем Sinchronize?? Просто от нечего делать?


 
Кипяток   (2004-03-25 15:09) [11]

2Defunct я по примеру с http://www.delphimaster.ru/articles/thread/ писал


 
Кипяток   (2004-03-25 15:10) [12]

2Digitman и что?


 
Кипяток   (2004-03-25 15:13) [13]

сорри у меня по другому моленько

begin
repeat
T1 := TMyThread1.Create(False);
T2 := TMyThread2.Create(False);
T1.Execute;
T2.Execute;
until false;
end.


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


 
Digitman ©   (2004-03-25 15:14) [14]


>  я думал что одно и тоже, а в чем разница


процесс и трэд - совершенно различные объекты ОС

процесс есть результат "запуска EXE" как такового

при старте процесса автоматически стартует как минимум один трэд, он называется "основным потоком процесса"

алгоритм, выполняемый любым тредом процесса (в т.ч. - основным), волен стартовать дополнительные трэды .. все стартованные треды живут "своей жизнью", но принадлежат контексту процесса и прекращают "жизнь" вместе со "смертью" процесса


 
Кипяток   (2004-03-25 15:18) [15]

2Digitman спасибо
еще вопрос, последний наверно
асли в одном из тредов readln то второй тоже ждать будет?


 
Digitman ©   (2004-03-25 15:20) [16]


> Кипяток   (25.03.04 15:10) [12]
>  и что?


что "и что" ?

ты создал объект ? будь любезен его уничтожить !

p.s.
кто-нть когда-нть наконец уберет эту дурацкую статью Кариха Николая (Nitro) с ресурса ? писал он ее абсолютно без башни


 
Digitman ©   (2004-03-25 15:26) [17]


> асли в одном из тредов readln то второй тоже ждать будет?


не будет

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

в том-то и весь смысл, что в осн.потоке конс.процесса ты стартовал дополнительные потоки и тут же "заснул" на readln

пока осн.поток ждет конс.ввода, прочие потоки заняты самым что ни на есть безобразно-параллельным исполнением того, что им указано в телах их методов Execute

как только произойдет конс.ввод, осн.поток "проснется", и это никак не отразится на ходе работы прочих потоков


 
KSergey ©   (2004-03-25 15:30) [18]

>  [13] Кипяток   (25.03.04 15:13)

Не надо вызывать Execute. Он сам вызовется системой при конструировании объекта, в случае, если указано  TMyThread1.Create(False);

Вообще поищите по форуму по "thread" - обсуждений про потоки много, были недавно, уверен почерпнете массу полезного и интересного.


 
Юрий Зотов ©   (2004-03-25 15:41) [19]

Значицца, дела такие.

1. DoWork - выбросьте. И больше никогда не следуйте чужим примерам вслепую, не разобравшись сначала в каждой строчке с помощью книг и справке. Думаете, все примеры в Интернете написаны корифеями? Большинство - как раз чайниками.

2. Код из DoWork перенесите внутрь цикла в Execute.

3. Execute вызывать не надо. В конструктре Вы передает False - значит, поток запустится сам.

4.
begin
 T1 := TMyThread1.Create(False); // Запустилcя поток 1
 T2 := TMyThread2.Create(False); // Запустилcя поток 2
 ... // А вот здесь надо что-то делать, иначе программа
 ... // завершится. И не забудьте уничтожить обеъкты:
 T2.Free;
 T1.Free;
end.


 
Кипяток   (2004-03-25 15:51) [20]


program console;
{$APPTYPE CONSOLE}
uses SysUtils, Classes;

type
   TMyThread = class(TThread)
protected
    procedure Execute; override;
end;

var
s:String;
MyThread:TMyThread;

procedure TMyThread.Execute;
begin
while not Terminated do
s:=s+"1" ;
end;

begin
MyThread:= TMyThread.Create(False);
readln;
writeln(s);
readln;
MyThread.Free;
end.


еще раз извините, но пример
по идее, как я понимаю, Тред запустился и мотает s:=s+"1" при нажатии ентера должен написать что там в s лежит, но у меня такое впечатление что он тикает только один раз и все(


 
Юрий Зотов ©   (2004-03-25 16:04) [21]

program Project1;

{$APPTYPE CONSOLE}

uses
 Classes;

type
 TMyThread = class(TThread)
 protected
   procedure Execute; override;
 end;

var
 I, N: integer;
 MyThread: TMyThread;

procedure TMyThread.Execute;
begin
 while not Terminated do
   if I = High(I) then I := 0 else Inc(I)
end;

begin
 I := 0;
 N := 0;
 MyThread := TMyThread.Create(False);
 try
   while N = 0 do
   begin
     WriteLn(I);
     ReadLn(N)
   end
 finally
   MyThread.Free
 end
end.


 
Кипяток   (2004-03-25 16:16) [22]

2Юрий Зотов огромное спасибо за пример, буду разбираться


 
Digitman ©   (2004-03-25 16:22) [23]


> Юрий Зотов


всегда был рад твоей, Юрий, поддержке ... в "работе с клиентом" .. когда слов, увы, уже не хватает .. и не только на тек.тему

спасибо


 
Юрий Зотов ©   (2004-03-25 16:50) [24]

А теперь самое интересное - я был КРАЙНЕ удивлен, обнаружив, что ГЛОБАЛЬНЫЕ переменные I и N оказались непроинициализированными компилятором D7. Пришлось обнулять их вручную. Во как!


 
MBo ©   (2004-03-25 16:58) [25]

>[24]
В D6 без оптимизации обнулены, с оптимизацией I =0, N - нет


 
Defunct ©   (2004-03-25 17:13) [26]

Надо обнулять при объявдении:

Var N: Integer = 0;

2 Юрий Зотов, это очень просто объясняется. Сегмент данных при включенной оптимизации кода располагается в верхних адресах и переменные просто не включаеются в EXE файл.

что-то типа такого:

code segment
;  ..
;  лалала наша программа
End code

stack segment
;..
end stack

data segment
;  Тут переменные заданные явно
;...
;в самых верхних адресах сегмента данных - объявленные переменные
;с произвольными значениями, они не попадают в EXE файл,
;соответственно инициализируются текущим значением ячеек памяти.
 N DD ?
 I DD ?
end data


 
Defunct ©   (2004-03-25 17:23) [27]

для пущей наглядности, если у вас имеется под рукой tasm и tlink
пробуйте откомпилировать такой код:

codes segment
assume cs:codes
org 100h
start:
 Ret
Field1  Db 512 Dup(?)
Filed2  Db "ENDP"
codes ends
end start


и такой:
codes segment
assume cs:codes
org 100h
start:
 Ret
Field1  Db 512 Dup(?)
Filed2  DD ?
codes ends
end start


В первом случае COM файл будет объемом 516 байт, в втором случае - 1 байт.


 
MBo ©   (2004-03-25 17:28) [28]

Defunct
Неприятно вот что (из хелпа):
1. If you don’t explicitly initialize a global variable, the compiler initializes it to 0.
2. All optimizations performed by the Object Pascal compiler are guaranteed not to alter the meaning of a program. In other words, Delphi performs no "unsafe" optimizations that require special awareness by the programmer.


 
Defunct ©   (2004-03-25 17:30) [29]

Я ж и говорю только при включенной оптимизации.


 
Юрий Зотов ©   (2004-03-25 17:36) [30]

> Defunct ©   (25.03.04 17:13) [26]

Это-то все понятно. Я удивился тому, что это не отражено в документации. Может не ту документацию я читал, но в той, что читал, ВЕЗДЕ сказано, что глобальные переменные инициализирутся автоматически. И ведь ничто не мешало компилятору вставить
N DD 0
I DD 0
поэтому и странно - а что бы ему так и не сделать?

Берем GUI-аналог той же самой программы - и видим, что N обнулена компилятором.

type
 TMyThread = class(TThread)
 protected
   procedure Execute; override;
 end;

 TForm1 = class(TForm)
   Button1: TButton;
   procedure FormCreate(Sender: TObject);
   procedure Button1Click(Sender: TObject);
   procedure FormClose(Sender: TObject; var Action: TCloseAction);
 private
   { Private declarations }
 public
   { Public declarations }
 end;

var
 Form1: TForm1;

implementation

{$R *.dfm}

var
 I, N: integer;
 MyThread: TMyThread;

procedure TMyThread.Execute;
begin
 while not Terminated do
   if I = High(I) then I := 0 else Inc(I)
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
 MyThread := TMyThread.Create(False);
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
 if N = 0 then Caption := IntToStr(I)
end;

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
 MyThread.Free
end;


 
Defunct ©   (2004-03-25 17:50) [31]

Юрий Зотов ©   (25.03.04 17:36) [30]

Могу предположить, что это сделано специально, т.к. в консольных приложениях, как правило, критичен размер исполнимого модуля. В документации должна быть оговорка для консольных приложений. Если найду, кину ссылку.

Тем не менее это очень хорошо, что Вы заметили эту особенность. Теперь хоть будем точно знать, что неявные переменные не включаются в exe, это большой плюс для D7, особенно когда глобальных переменных много, а иницализировать их не требуется.


 
Юрий Зотов ©   (2004-03-25 18:00) [32]

> Defunct ©   (25.03.04 17:50) [31]

> Теперь хоть будем точно знать, что неявные переменные не
> включаются в exe, это большой плюс для D7

Компилятор Delphi шибко умный, при включенной оптимизации он много чего может повыкинуть, а уж неявные/неиспользуемые переменные и неиспользуемые процедуры/методы - так это вообще его любимая добыча, на счет "раз" хрумкает. И не только в D7, в более ранних тоже.

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


 
Verg ©   (2004-03-25 19:53) [33]


> В то же время, он запросто может не вынести из цикла откровенный
> инвариант. Тоже удивительно.


Нет volatile.


 
Юрий Зотов ©   (2004-03-25 19:57) [34]

> Verg ©   (25.03.04 19:53) [33]

Вы упустили из виду слово "откровенный". То есть - никаких volatile.



Страницы: 1 вся ветка

Форум: "Основная";
Текущий архив: 2004.04.11;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.54 MB
Время: 0.041 c
1-1082625987
Anthony
2004-04-22 13:26
2004.04.11
Как записать массив в *.ini файл?


3-1082039565
miwa
2004-04-15 18:32
2004.04.11
Приведенный код выдает -805-ю ошибку


1-1080175040
LoMaster
2004-03-25 03:37
2004.04.11
программа, удаляющая сама себя


1-1082458886
Nemra
2004-04-20 15:01
2004.04.11
FastReport


14-1082002931
wHammer
2004-04-15 08:22
2004.04.11
ТASM





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский