Форум: "Основная";
Текущий архив: 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.049 c