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

Вниз

Как приостановить поток?   Найти похожие ветки 

 
Fay ©   (2005-08-23 15:43) [40]

Reindeer Moss Eater ©   (23.08.05 15:43) [38]
он может уснуть ГДЕ УГОДНО


 
Reindeer Moss Eater ©   (2005-08-23 15:45) [41]

Fay, что ты мне хочешь доказать?
Что это не лучший способ?
Так я еще с десяток постов назад сказал, что не стал бы так делать.


 
Fay ©   (2005-08-23 15:47) [42]

2 Reindeer Moss Eater ©   (23.08.05 15:45) [41]
Я и не утверждаю, что ты стал бы так делать. Просто говорю - так низя.


 
Leonid Troyanovsky ©   (2005-08-23 16:03) [43]


Alexander Panov ©   (23.08.05 15:43) [39]

>> А если он заснет посредине, скажем, Move?

> Он сам заснет, что-ли?


Это не моя терминология.


> Reindeer Moss Eater ©   (23.08.05 14:15) [23]
> Вторичным потоком рулит первичный.
> Он ему делает суспенд.
> Список изменяется только когда вторичный поток уснул.


А остановить его могут на любой атомарной операции.


> Кстати, даже четырехбайтовых значений положено InterLocked*

> Это если используется блокировка Interlocked-функциями.


Дык, и надо ее пользовать. Даже для однобайтовых.

--
Regards, LVT.


 
Внук ©   (2005-08-23 16:20) [44]

>>Alexander Panov ©   (23.08.05 15:43) [39]
 Не смoжешь ты контролировать, когда именно уснет поток. И дело не в том, кто как пишет программы :) Но через Suspend надежной синхронизации не получится.


 
Alexander Panov ©   (2005-08-23 16:45) [45]

Внук ©   (23.08.05 16:20) [44]
Не смoжешь ты контролировать, когда именно уснет поток. И дело не в том, кто как пишет программы :) Но через Suspend надежной синхронизации не получится.


А мне и не нужно знать, когда он уснет после моей команды ему. Мне достаточно перед усыплением дождаться, пока поток закончит обработку защищаемых данных, взвести флаг о том, что данные используются в другом потоке, после этого усыпить его. И все. Надежней некуда.


 
Leonid Troyanovsky ©   (2005-08-23 16:50) [46]


> Alexander Panov ©   (23.08.05 16:45) [45]
> Внук ©   (23.08.05 16:20) [44]
> Не смoжешь ты контролировать, когда именно уснет поток.

> А мне и не нужно знать, когда он уснет после моей команды
> ему. Мне достаточно перед усыплением дождаться, пока поток
> закончит обработку защищаемых данных,


А тогда и не требуется его усыплять (приостанавливать).
Закончил обработку (write) - данные консистентны.

--
Regards, LVT.


 
Alexander Panov ©   (2005-08-23 17:13) [47]

Leonid Troyanovsky ©   (23.08.05 16:50) [46]
тогда и не требуется его усыплять (приостанавливать).


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


 
Leonid Troyanovsky ©   (2005-08-23 17:25) [48]


> Alexander Panov ©   (23.08.05 17:13) [47]

>> тогда и не требуется его усыплять (приостанавливать).

> Не требуется, если это не нужно.
> А если нужно, то никто не мешает это сделать, причем совершенно
> потокобезопасно относительно совместной работы с данными
> этого и других потоков.


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

--
Regards, LVT.


 
Alexander Panov ©   (2005-08-23 17:41) [49]

Leonid Troyanovsky ©   (23.08.05 17:25) [48]
Т.е., зачем оно может требоваться для синхронизации,
если оная уже произошла.


Например, остановить поток для того, чтобы
1. Безопасно работать с другими данными, либо не дать потоку захватить другие данные.
2. Не разрешать потоку холостых циклов.


 
Leonid Troyanovsky ©   (2005-08-23 17:48) [50]

> Alexander Panov ©   (23.08.05 17:41) [49]
> Leonid Troyanovsky ©   (23.08.05 17:25) [48]
> Т.е., зачем оно может требоваться для синхронизации,
> если оная уже произошла.

> Например, остановить поток для того, чтобы
> 1. Безопасно работать с другими данными, либо не дать потоку
> захватить другие данные.
> 2. Не разрешать потоку холостых циклов.


Дык,
1. Эта другая задача синхронизации.
2. Откуда взяться холостым циклам, если поток должен ждать
синхронизирующих событий, т.е., должен спать (уже в терминологии Рихтера).

--
Regards, LVT.


 
Alexander Panov ©   (2005-08-23 18:02) [51]

Leonid Troyanovsky ©   (23.08.05 17:48) [50]
2. Откуда взяться холостым циклам, если поток должен ждать
синхронизирующих событий, т.е., должен спать (уже в терминологии Рихтера).


Так весь сыр-бор в ветке из-за того, можно или нет обойтись без объектов синхронизации.


 
han_malign ©   (2005-08-23 18:27) [52]

>Так весь сыр-бор в ветке из-за того, можно или нет обойтись без объектов синхронизации.
- дык Suspend никаким боком к синхронизации и не относится...
This function is primarily designed for use by debuggers. It is not intended to be used for thread synchronization. Calling SuspendThread on a thread that owns a synchronization object, such as a mutex or critical section, can lead to a deadlock if the calling thread tries to obtain a synchronization object owned by a suspended thread. To avoid this situation, a thread within an application that is not a debugger should signal the other thread to suspend itself. The target thread must be designed to watch for this signal and respond appropriately.


 
Alexander Panov ©   (2005-08-23 19:09) [53]

han_malign ©   (23.08.05 18:27) [52]

Хочешь пример, где можно синхронизацию осуществить методами Suspend/Resume?


 
Fay ©   (2005-08-23 22:33) [54]

2 Alexander Panov ©   (23.08.05 19:09) [53]
Я, конечно, не han_malign, но давно жду такой пример.
Будьте так добры...


 
Alexander Panov ©   (2005-08-24 00:44) [55]

Вот совершенно простой пример:

unit Unit1;

interface

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

type
 TForm1 = class(TForm)
   Memo1: TMemo;
   Button1: TButton;
   Label1: TLabel;
   Button2: TButton;
   procedure Button1Click(Sender: TObject);
   procedure Button2Click(Sender: TObject);
   procedure FormClose(Sender: TObject; var Action: TCloseAction);
 private
   { Private declarations }
 public
   { Public declarations }
 end;

 TTest=class(Tthread)
 private
   FMemo: TMemo;
   procedure UpdateMemo;
 protected
   procedure Execute; override;
 public
   constructor Create(Memo: TMemo);
 end;

var
 Form1: TForm1;
 Test: Ttest;
 isTerminate: Boolean;

implementation

{$R *.dfm}

{ TTest }

constructor TTest.Create(Memo: TMemo);
begin
   inherited Create(True);
   FreeOnTerminate := True;
   FMemo := Memo;
   Resume;
end;

procedure TTest.Execute;
begin
   while not Terminated do
   begin
      UpdateMemo;
      Sleep(2000);
      Suspend;
   end;
end;

procedure TTest.UpdateMemo;
begin
   FMemo.Lines.Add("Доп. поток: состояние расчетов");
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
   Test := TTest.Create(Memo1);
   isTerminate := False;
   with Test do
   begin
       while not isTerminate do
       begin
           if Suspended then
           begin
               Memo1.Lines.Add("Основной поток: работаю с Memo1");
               Label1.Caption := "Основной поток: Работаю";
               Application.ProcessMessages;
               Sleep(1000);
               Resume;
           end;
           while not Suspended do
           begin
               Label1.Caption := "Основной поток: жду освобождения ресурса";
               Application.ProcessMessages;
           end;
       end;
       Label1.Caption := "Поток закончил работу";
       Terminate;
   end;
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
 isTerminate := True;
end;

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
 isTerminate := True;
end;

end.


 
Alexander Panov ©   (2005-08-24 00:47) [56]

Взять пример можно здесь:
ftp://ftp.almar.net.ru/pub/simplethread/simplethread.zip


 
Defunct ©   (2005-08-24 01:07) [57]

> Alexander Panov

Пример бесспорно рабочий, но не решает сабжевый вопрос. Всмысле конанду доп потоку на приостановку должен отдавать основной поток. Если можете, подправьте код, (там собсно нечего подправлять, флажек один добавить) было бы интересно и познавательно для всех.


 
Alexander Panov ©   (2005-08-24 01:25) [58]

Defunct ©   (24.08.05 1:07) [57]

Напрямую использовать Suspend потоку все равно не получится.

А вот так можно сделать:

unit Unit1;

interface

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

type
 TForm1 = class(TForm)
   Memo1: TMemo;
   Button1: TButton;
   Label1: TLabel;
   Button2: TButton;
   procedure Button1Click(Sender: TObject);
   procedure Button2Click(Sender: TObject);
   procedure FormClose(Sender: TObject; var Action: TCloseAction);
 private
   { Private declarations }
 public
   { Public declarations }
 end;

 TTest=class(Tthread)
 private
   FTrySuspend: Boolean;
   FMemo: TMemo;
   procedure UpdateMemo;
 protected
   procedure Execute; override;
 public
   constructor Create(Memo: TMemo);
   procedure Suspend;
 end;

var
 Form1: TForm1;
 Test: Ttest;
 isTerminate: Boolean;

implementation

{$R *.dfm}

{ TTest }

constructor TTest.Create(Memo: TMemo);
begin
   inherited Create(True);
   FreeOnTerminate := True;
   FMemo := Memo;
   FTrySuspend := False;
   Resume;
end;

procedure TTest.Execute;
begin
   while not Terminated do
   begin
      UpdateMemo;
      Sleep(2000);
      if FTrySuspend then
      begin
        FTrySuspend := False;
        Suspended := True;
      end;
   end;
end;

procedure TTest.Suspend;
begin
   FTrySuspend := True;
end;

procedure TTest.UpdateMemo;
begin
   FMemo.Lines.Add("Доп. поток: состояние расчетов");
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
    Test := TTest.Create(Memo1);
    isTerminate := False;
    while not isTerminate do
    begin
        Test.Suspend;
        while not Test.Suspended do
        begin
            Label1.Caption := "Основной поток: жду освобождения ресурса";
            Application.ProcessMessages;
            if isTerminate then Break;
        end;
        Memo1.Lines.Add("Основной поток: работаю с Memo1");
        Label1.Caption := "Основной поток: Работаю";
        Application.ProcessMessages;
        Sleep(1000);
        Test.Resume;
    end;
    Label1.Caption := "Поток закончил работу";
    Test.Terminate;
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
 IsTerminate := True;
end;

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
 IsTerminate := True;
end;

end.


 
Alexander Panov ©   (2005-08-24 01:27) [59]

ftp://ftp.almar.net.ru/pub/simplethread/simplethread1.zip


 
Defunct ©   (2005-08-24 01:38) [60]

> Alexander Panov

Вполне приличное решение. Даже вероятно в некоторых случаях лучше чем крит. секция.

Только, я бы добавил еще следующее изменение, чтобы после вызова suspend управляющий поток гарантировано мог работать с данными остановленного потока без лишних проверок:

procedure TTest.Suspend;
begin
 fTrySuspend := True;
 while fTrySuspend do
 begin
   sleep(10);
   Application.ProcessMessages
 end
end;


 
Внук ©   (2005-08-24 08:48) [61]

>>Alexander Panov ©   (23.08.05 16:45) [45]
>>Alexander Panov ©   (24.08.05 01:25) [58]
 Угу, это гарантирует безопасный доступ к данным, но во время  работы второго потока первый может еще не перейти в состояние приостановки, то есть ему все еще будет выделяться процессорное время. Да и приостанавливать его, как уже отмечали, в этом случае необязательно. Таким образом, мы говорим об одном и том же, только я не считаю возможным в этом случае использовать термин "синхронизация" :)


 
Игорь Шевченко ©   (2005-08-24 09:47) [62]

Иван Кулибин в гробу от зависти переворачивается.


 
Alexander Panov ©   (2005-08-24 10:01) [63]

Игорь Шевченко ©   (24.08.05 9:47) [62]

"Голь на выдумки хитра" ;)


 
Fay ©   (2005-08-24 14:06) [64]

2 Alexander Panov ©   (24.08.05 1:27) [59]
Во-первых...
Посмотрите загрузку процессора.


 
Alexander Panov ©   (2005-08-24 14:07) [65]

Fay ©   (24.08.05 14:06) [64]
Во-первых...
Посмотрите загрузку процессора.


А что, были разговоры про загрузку процессора?


 
Fay ©   (2005-08-24 16:47) [66]

2 Alexander Panov ©   (24.08.05 14:07) [65]

Ошибку можно ждать долго.
Я несколько модифицировал приведённый код.
Если модификация не кажется правомерной - скажите.

Если во время работы программы перетащить форму - будет галюн.

unit Unit1;

interface

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

type
 PPInteger = ^PInteger;
 TForm1 = class(TForm)
   Button1 : TButton;
   Label1 : TLabel;
   Button2 : TButton;
   procedure Button1Click(Sender : TObject);
   procedure Button2Click(Sender : TObject);
   procedure FormClose(Sender : TObject; var Action : TCloseAction);
 end;

 TTest = class(Tthread)
 private
   FTrySuspend : Boolean;
   FP : PPInteger;
   procedure UpdateMemo;
 protected
   procedure Execute; override;
 public
   constructor Create(p : PPInteger); reintroduce;
   procedure Suspend;
 end;

var
 Form1 : TForm1;
 Test : Ttest;
 isTerminate : Boolean;

implementation

{$R *.dfm}

{ TTest }

constructor TTest.Create(p : PPInteger);
begin
 inherited Create(True);
 FreeOnTerminate := True;
 FP := p;
 FTrySuspend := False;
 Resume;
end;

procedure TTest.Execute;
begin
 while not Terminated do
   begin
     UpdateMemo;
     if FTrySuspend then
       begin
         FTrySuspend := False;
         // Sleep(100);
         Suspended := True;
       end;
   end;
end;

procedure TTest.Suspend;
begin
 FTrySuspend := True;
end;

procedure TTest.UpdateMemo;
var
 p : PInteger;
begin
 p := FP^;
 FP^ := nil;
 Sleep(555);
 FP^ := p;
end;

procedure TForm1.Button1Click(Sender : TObject);
var
 n : Integer;
 p : PInteger;
begin
 n := 0;
 p := @n;  
 Test := TTest.Create(@p);
 isTerminate := False;
 while not isTerminate do
   begin
     Test.Suspend;
     while not Test.Suspended do
       begin
         Label1.Caption := "Основной поток: жду освобождения ресурса";
         Application.ProcessMessages;
          // Тут выяснилось, что кнопку Button2 нажали
         // if isTerminate then
         Break;
       end;
     Label1.Caption := "Основной поток: Работаю";
     Application.ProcessMessages;
     Inc(p^);
     Sleep(777);
     Inc(p^);
     Test.Resume;
   end;
 Label1.Caption := "Поток закончил работу";
 Test.Terminate;
end;

procedure TForm1.Button2Click(Sender : TObject);
begin
 IsTerminate := True;
end;

procedure TForm1.FormClose(Sender : TObject; var Action : TCloseAction);
begin
 IsTerminate := True;
end;

end.


 
Fay ©   (2005-08-24 17:04) [67]

Можно несколько упростить.

procedure TTest.UpdateMemo;
var
 p : PInteger;
begin
 p := FP^;
 FP^ := nil;
 Application.ProcessMessages;
 FP^ := p;
end;

procedure TForm1.Button1Click(Sender : TObject);
var
 n : Integer;
 p : PInteger;
begin
 n := 0;
 p := @n;  
 Test := TTest.Create(@p);
 isTerminate := False;
 while not isTerminate do
   begin
     Test.Suspend;
     while not Test.Suspended do
       begin
         Label1.Caption := "Основной поток: жду освобождения ресурса";
         Application.ProcessMessages;
          // Тут выяснилось, что кнопку Button2 нажали
         // if isTerminate then
         if n > 10 then
         Break;
       end;
     Label1.Caption := "Основной поток: Работаю";
     Application.ProcessMessages;
     Inc(p^);
     Test.Resume;
   end;
 Label1.Caption := "Поток закончил работу";
 Test.Terminate;
end;


 
Fay ©   (2005-08-24 17:59) [68]

2 Alexander Panov
Ау! Вы где? Ваш, IMO, пример кривой!


 
Alexander Panov ©   (2005-08-24 18:25) [69]

Fay ©   (24.08.05 16:47) [66]
Если во время работы программы перетащить форму - будет галюн.


А кто сказал, что пример на это расчитан?

Замени TMemo на TStringList - ошибка исчезнет.


 
Fay ©   (2005-08-24 18:34) [70]

2 Alexander Panov ©   (24.08.05 18:25) [69]
Ничего не нужно таскать. Просто надо взять [67]


 
Fay ©   (2005-08-24 18:45) [71]

Alexander Panov ©   (24.08.05 18:25) [69]
... да и нет там никакого Memo ...


 
Defunct ©   (2005-08-24 18:58) [72]

> Fay

А такой вариант не глючит, и процессорное время не хавает.

 type
   TThreadEx = class(TThread)
   private
      fMemo       : TMemo;
      fTrySuspend : boolean;

      procedure Execute;override;
   public
      procedure Suspend;
      constructor Create(AMemo : TMemo);
   end;

constructor TThreadEx.Create;
begin
 if not Assigned( AMemo ) then
    raise Exception.Create("не насилуй");
 fMemo := AMemo;
 inherited Create( True );
 FreeOnTerminate := True;
 fTrySuspend := false;
 resume;
end;

procedure TThreadEx.Suspend;
begin
 fTrySuspend := True;
 while not fTrySuspend do
 begin
   sleep(0);
   //Application.ProcessMessages;
 end;
end;

procedure TThreadEx.Execute;
begin
 while not Terminated do
 begin
    fMemo.Lines.Text := "работает доп поток";

    if fTrySuspend then
    begin
       fTrySuspend := False;
       fMemo.Lines.Text := "доп поток остановлен по требованию";
       inherited Suspend;
    end;
 end;
end;



var
 ThreadEx : TThreadEx = nil;

procedure TForm1.Button1Click(Sender: TObject);
begin
 ThreadEx := TThreadEx.Create( Memo1 );
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
 if Assigned( ThreadEx ) then
 begin
    ThreadEx.Suspend;
    Memo1.Lines.Text := "Поток остановлен";
 end;
end;

procedure TForm1.Button3Click(Sender: TObject);
begin
 if Assigned( ThreadEx ) then
 begin
    ThreadEx.Resume;
 end;
end;


 
Fay ©   (2005-08-24 19:06) [73]

2 Defunct ©   (24.08.05 18:58) [72]
Первое впечатление : совершенно не понятно, что демонстрирует пример. Защиту чего от чего?
Можно полный код?

P.S.
Проверки if Assigned( ThreadEx ) не надёжны, т.к. FreeOnTerminate := True;


 
Fay ©   (2005-08-24 19:09) [74]

Fay ©   (24.08.05 19:06) [73]
Так же не вижу (я, конечно, ещё посмотрю внимательно), где ThreadEx := nil. Без этого if Assigned(ThreadEx) не имеет смысла.


 
Defunct ©   (2005-08-24 19:27) [75]

Fay ©   (24.08.05 19:06) [73]
> Защиту чего от чего?

Пофантазируйте. Поставьте

ThreadEx.Suspend;
< меняем поля ThreadEx >
ThreadEx.Resume;


 
Defunct ©   (2005-08-24 19:37) [76]

> Fay
> Проверки if Assigned( ThreadEx ) не надёжны, т.к. FreeOnTerminate := True;

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


 
Fay ©   (2005-08-24 19:57) [77]

2 Defunct ©   (24.08.05 19:37) [76]

Я тут немного пофантазировал. Попробуйте 8).

unit Unit1;

interface

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

type
 PPInteger = ^PInteger;
 TForm1 = class(TForm)
   Button1 : TButton;
   Label1 : TLabel;
   Button2 : TButton;
   Button3 : TButton;
   procedure Button1Click(Sender : TObject);
   procedure Button2Click(Sender : TObject);
   procedure Button3Click(Sender : TObject);
 end;

 TThreadEx = class(TThread)
 private
   FTrySuspend : Boolean;
   FP : PPInteger;
 protected
   procedure Execute; override;
 public
   constructor Create(p : PPInteger); reintroduce;
   procedure Suspend;
 end;

var
 Form1 : TForm1;

implementation

{$R *.dfm}

var
 ThreadEx : TThreadEx = nil;

constructor TThreadEx.Create(p : PPInteger);
begin
 inherited Create(True);
 if not Assigned(p^) then
   raise Exception.Create("не насилуй");
 FP := p;
 FreeOnTerminate := True;
 fTrySuspend := false;
 Resume;
end;

procedure TThreadEx.Execute;
 procedure DoIt;
 var
   p : PInteger;
 begin
   p := FP^;
   FP^ := nil;
   Sleep(0); // Потоку ничто не мешает переключиться именно здесь
   FP^ := p;
 end;
begin
 while not Terminated do
   begin
     DoIt;
     if fTrySuspend then
       begin
         fTrySuspend := False;
         inherited Suspend;
       end;
   end;
end;

procedure TThreadEx.Suspend;
begin
 FTrySuspend := True;
 while not fTrySuspend do
   Sleep(0);
end;

procedure TForm1.Button1Click(Sender : TObject);
var
 n : Integer;
 p : PInteger;
begin
 n := 0;
 p := @n;
 ThreadEx := TThreadEx.Create(@p);
 repeat
   ThreadEx.Suspend;
   Inc(p^);
   Caption := IntToStr(p^);
   Application.ProcessMessages;
   ThreadEx.Resume;
 until p^ >= 999;
 ThreadEx := nil;
end;

procedure TForm1.Button2Click(Sender : TObject);
begin
 if Assigned(ThreadEx) then
   ThreadEx.Resume;
end;

procedure TForm1.Button3Click(Sender : TObject);
begin
 if Assigned(ThreadEx) then
   ThreadEx.Suspend;
end;

end.



 
Defunct ©   (2005-08-24 21:03) [78]

Fay ©   (24.08.05 19:57) [77]

По меньшей мере вы делаете преднамерено небезопастный код, игнорируете синхронизацию - обращаетесь к незащищенной переменной в until, т.к. обращения к P^ безопастны только между Suspend<->Resume.

Знаете, можно и с крит. секцией сделать такую ошибку.

procedure TThreadEx.Execute;
...
  CS.Acquire;
  try
     DoIt;
  finally
     CS.Release
  end;
...
end;

ThreadEx := TThreadEx.Create(@p);
repeat
  ThreadEx.Suspend;
  CS.Acquire;
  try            <--- ЗДЕСЬ ОБРАЩЕНИЕ К P^ БЕЗОПАСТНО
    Inc(p^);
    Caption := IntToStr(p^);
  finally
    CS.Release;
  end;
  Application.ProcessMessages;
  ThreadEx.Resume;
until p^ >= 999;  <--- ЗДЕСЬ ТОЖЕ ТРЕБУЕТСЯ ЗАЩИТА
                  <--- ЛИБО БУДЬТЕ ДОБРЫ СКОПИРУЙТЕ ЗНАЧЕНИЕ,
                  <--- НА ТОМ УЧАСТКЕ КОДА, ГДЕ ОБРАЩЕНИЕ
                  <--- К P^ БЫЛО ЗАЩИЩЕНО.
ThreadEx := nil;


 
Fay ©   (2005-08-24 21:14) [79]

2 Defunct ©   (24.08.05 21:03) [78]
until n >= 999


 
Fay ©   (2005-08-24 21:17) [80]

Defunct ©   (24.08.05 21:03) [78]

Со всеми бывает. У меня ещё других дел хватает, проглядел.
Пусть будет так 8)

var
 n, i : Integer;
 p : PInteger;
begin
 n := 0;
 p := @n;
 ThreadEx := TThreadEx.Create(@p);
 repeat
   ThreadEx.Suspend;
   Inc(p^);
   Caption := IntToStr(p^);
   Application.ProcessMessages;
   i := n;
   ThreadEx.Resume;
 until i >= 999;
 ThreadEx := nil;



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

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

Наверх




Память: 0.65 MB
Время: 0.016 c
14-1124828773
ronyn
2005-08-24 00:26
2005.09.18
В чем различие между DDR и DDR-II


9-1116873712
iosif
2005-05-23 22:41
2005.09.18
Нужен пример OpenGL


14-1124384456
maximsm
2005-08-18 21:00
2005.09.18
Win XP права пользоваелей


14-1124638541
Alexander Panov
2005-08-21 19:35
2005.09.18
Опять спор об исключениях.


1-1125249838
heady
2005-08-28 21:23
2005.09.18
работать с Tmemo как с тесктовывм файлом





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский