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

Вниз

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

 
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;


 
Defunct ©   (2005-08-24 21:58) [81]

> Fay

Вы намекаете на то, что поток останавливается не сразу после inherited suspend? если оно так.. тогда конечно, ни пример АП, ни мой, не годятся.


 
Defunct ©   (2005-08-24 22:11) [82]

с учетом [81] такой вариант синхронизации проходит ваш тест, однако я соглашусь с тем что крит. секция была бы более рациональным решением..

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

var
 Form2: TForm2;

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;
        while not fResumed do sleep(0);
      end;
  end;
end;

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

procedure TThreadEx.Resume;
begin
 inherited Resume;
 fResumed := True;
end;


 
Fay ©   (2005-08-25 00:54) [83]

2 Defunct ©   (24.08.05 22:11) [82]
Щяз, думаю, испорчу впечатление.


 
Defunct ©   (2005-08-25 01:29) [84]

> Fay

Наврятли, тут уже все по канонам семафоров.


 
Fay ©   (2005-08-25 01:36) [85]

2 Defunct ©   (25.08.05 1:29) [84]

>> Наврятли
Фигушки. Улучшений не наблюдается.
Выслать?

>> тут уже все по канонам семафоров
Сомневаюсь 8).


 
Fay ©   (2005-08-25 01:41) [86]

2 Defunct ©   (25.08.05 1:29) [84]
Выслал на указанное в анкете мыло.
Собственно, хто угодно в состоянии добавить в [80] и [82] к [77]...


 
Fay ©   (2005-08-25 01:43) [87]

2 Defunct ©   (24.08.05 22:11) [82]

FTrySuspend := True;
while not fTrySuspend do

 Sleep(0);


Это вАщЕ шедевр 8)


 
Defunct ©   (2005-08-25 02:01) [88]

> Fay
пока не пришло. жду ;>

> Fay ©   (25.08.05 01:43) [87]

хаха, и действительно.
Поделиться травой? ;>
Да, уж я тоже не углядел.

Сейчас сделаю нормальный вариант


 
Defunct ©   (2005-08-25 02:11) [89]

Собсно там и делать ничего не пришлось, просто исправать указанную вами строчку:

> while fTrySuspend do

просто в моем изначальном примере поле называлось fFrozen, и было while not fFrozen do sleep.. при переделке поменял название и логику переменной, а про not забыл и капцы ;>

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

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 fTrySuspend do
        Sleep(0);
end;


 
Fay ©   (2005-08-25 02:22) [90]

2 Defunct ©   (25.08.05 2:11) [89]

Мне не удалось выйти из второй итерации

unit Unit1;

interface

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

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

 TThreadEx = class(TThread)
 private
   FTrySuspend : Boolean;
   FP : PPInteger;
   FResumed : Boolean;
 protected
   procedure Execute; override;
 public
   constructor Create(p : PPInteger); reintroduce;
   procedure Suspend;
   procedure Resume;
 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;
         while not fResumed do
           sleep(0);
       end;
   end;
end;

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

procedure TThreadEx.Resume;
begin
 inherited Resume;
 FResumed := True;
end;

procedure TForm1.Button1Click(Sender : TObject);
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;
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-25 02:34) [91]

Fay ©   (25.08.05 02:22) [90]

Да, там deadlock...
Попробуйте [89]


 
Fay ©   (2005-08-25 02:38) [92]

2 Defunct ©   (25.08.05 2:34) [91]
Я тут весь пью пиво, зоркость ума сбилась.
Приведите, plz, просто код процедур для замены. Если не сложно...


 
Defunct ©   (2005-08-25 02:45) [93]

> Fay ©   (25.08.05 02:38) [92]

Просто замените весь класс TThreadEx на [89].
Там поменялось:
- suspend
- execute
- выброшено поле fResumed
- выброшена модификация метода Resume


 
Fay ©   (2005-08-25 03:12) [94]

2 Defunct ©   (25.08.05 2:45) [93]

DoIt вывел наружу (просто так).
Добавил Sleep(0) в Execute;

unit Unit1;

interface

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

type
 PPInteger = ^PInteger;
 TForm1 = class(TForm)
   Button1 : TButton;
   Button2 : TButton;
   procedure Button1Click(Sender : TObject);
   procedure Button2Click(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 DoIt(var p : PInteger);
var
 tmp : PInteger;
begin
 tmp := p;
 p := nil;
 p := tmp;
end;

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

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

procedure TForm1.Button1Click(Sender : TObject);
var
 n, i : Integer;
 p : PInteger;
begin
 n := 0;
 p := @n;
 ThreadEx := TThreadEx.Create(@p);
 repeat
   ThreadEx.Suspend; // (1) Выполняется в основном потоке
   Inc(p^);
   Caption := IntToStr(p^);
   Application.ProcessMessages;
   i := n;
   ThreadEx.Resume;
 until i >= 999;
 ThreadEx.Terminate;
 ThreadEx := nil;
end;

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

end.



 
Fay ©   (2005-08-25 03:30) [95]

Кошки-мышки-крыски-жучки какие-то 8)


 
Defunct ©   (2005-08-25 03:32) [96]

> // Потоку ничто не мешает переключиться именно здесь

Ваша правда.. и это приводит к deadlock"у.
в таком случае меняем suspend так:

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


 
Defunct ©   (2005-08-25 03:36) [97]

Fay ©   (25.08.05 03:30) [95]

а вы хотели чтобы тут кто-то сходу выдал решение через "задницу" с одним только suspend, надежное как RTLCS? ;>

надеюсь [96] будет последней модификацией ;>


 
Fay ©   (2005-08-25 04:33) [98]

2 Defunct ©   (25.08.05 3:36) [97]

Это код из генофонда.
Для глюка хватит переключения потока в выделенном месте.

procedure TThread.Suspend;
var
 OldSuspend: Boolean;
begin
 OldSuspend := FSuspended;
 try
   FSuspended := True;
   // Выделенное место
{$IFDEF MSWINDOWS}
   CheckThreadError(Integer(SuspendThread(FHandle)) >= 0);
{$ENDIF}
{$IFDEF LINUX}
   CheckThreadError(pthread_kill(FThreadID, SIGSTOP));
{$ENDIF}
 except
   FSuspended := OldSuspend;
   raise;
 end;
end;


Может уже хватит моделировать ошибки? 8)
Просто я не верю, что Вы - убеждённый борец за защиту данных с пом. Suspend...


 
Fay ©   (2005-08-25 04:37) [99]

К [98]
Не "хватит", а "необходимо".


 
Fay ©   (2005-08-25 04:38) [100]

К [99]
В с мысле "Для глюка необходимо..."


 
Slym ©   (2005-08-25 04:57) [101]

Гомики так и получаются, от использования ануса не по назначению.


 
Fay ©   (2005-08-25 05:02) [102]

2 Defunct ©   (25.08.05 3:36) [97]
[98] - [100] бред.
Я чуть не сдвинулся модель рисовать 8)
Способ действительно работает. Но только именно с парой потоков. Т.е. с тремя (два ведут себя как основной в примере) не прокатит. Производительность никакая, но мы ведь не это обсуждаем 8)).


 
Fay ©   (2005-08-25 05:02) [103]

Но я ещё подумаю 8))


 
Defunct ©   (2005-08-25 07:01) [104]

> Fay
> Просто я не верю, что Вы - убеждённый борец за защиту данных с пом. Suspend...

И правильно делаете. Интересно было только показать, что и такой способ синхронизации имеет место, и вполне работоспособен.


 
volser   (2005-08-25 16:40) [105]

Я попробовал сделать совй пример с помощью крит секций, но у меня иногда все подвисает. Возможен ли с крит. секц. дедлок?


 
Leonid Troyanovsky ©   (2005-08-25 16:58) [106]


> volser   (25.08.05 16:40) [105]
> Я попробовал сделать совй пример с помощью крит секций,
> но у меня иногда все подвисает. Возможен ли с крит. секц.
> дедлок?


Конечно.
При неправильном ея употреблении.

--
Regards, LVT.


 
Fay ©   (2005-08-25 17:17) [107]

2 Defunct ©   (25.08.05 7:01) [104]
Работоспособен не метод, а применение его в нек. ситуациях, на которые есть существенные ограничения:
1) один из потоков должен знать про второй
2) потоков должно быть ровно два

К тому же, очевидно, подобную защиту нельзя встроить в сам защищаемый объект. Короче - полные дрова.


 
Alexander Panov ©   (2005-08-25 17:56) [108]

Fay ©   (25.08.05 17:17) [107]
1) один из потоков должен знать про второй
2) потоков должно быть ровно два


Совершенно необязательные условия.


 
Fay ©   (2005-08-25 17:59) [109]

2 Alexander Panov ©   (25.08.05 17:56) [108]
Многоуважаемый не потрудится объяснить, как вызвать метод объекта, не зная о его существовании?


 
Alexander Panov ©   (2005-08-25 18:02) [110]

Alexander Panov ©   (25.08.05 17:56) [108]

Это про что?
При чем здесь неизвестные методы?


 
Fay ©   (2005-08-25 18:08) [111]

2 Alexander Panov ©   (25.08.05 18:02) [110]
Suspend и Resume - это ведь методы?


 
Alexander Panov ©   (2005-08-25 18:12) [112]

Fay ©   (25.08.05 18:08) [111]
Suspend и Resume - это ведь методы?


Конечно. И они есть у каждого наследника TThread.


 
Fay ©   (2005-08-25 18:18) [113]

2 Alexander Panov ©   (25.08.05 18:12) [112]

Ну и как же их вызвать, не зная о сужествовании экземпляря?


 
Alexander Panov ©   (2005-08-25 18:31) [114]

Fay ©   (25.08.05 18:18) [113]
Ну и как же их вызвать, не зная о сужествовании экземпляря?


Это смотря как написать - уже снова повторяю тезис.


 
Игорь Шевченко ©   (2005-08-25 18:32) [115]

И все-таки, зачем ?


 
Alexander Panov ©   (2005-08-25 18:33) [116]

Игорь Шевченко ©   (25.08.05 18:32) [115]
И все-таки, зачем ?


Чтобы проявить смекалку;)


 
Alexander Panov ©   (2005-08-25 18:34) [117]

Игорь Шевченко ©   (25.08.05 18:32) [115]

Мало ли для чего иногда возникает надобность в извратах.


 
Игорь Шевченко ©   (2005-08-25 18:39) [118]

Alexander Panov ©   (25.08.05 18:33) [116]

Судя по длине ветки и количеству глюков, это не совсем смекалка.


 
Fay ©   (2005-08-25 18:40) [119]

2 Alexander Panov ©   (25.08.05 18:31) [114]
Пока я не видел примера без вызова метода экземпляра. Думаю, не увижу.


 
Alexander Panov ©   (2005-08-25 18:44) [120]

Fay ©   (25.08.05 18:40) [119]
Думаю, не увижу.


Думаю, что да. Не вижу смысла в том.
Все дело только лишь в желании сделать, а не в методах.



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

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

Наверх





Память: 0.69 MB
Время: 0.021 c
1-1124994267
TStas
2005-08-25 22:24
2005.09.18
Как подключить файл помощи?


3-1123103366
Silver...
2005-08-04 01:09
2005.09.18
ADODataSet.Filter --- и поле типа Boolean


1-1124915937
Ginger
2005-08-25 00:38
2005.09.18
Готовый парсер xml-документа в описание формы


3-1123162846
Sansy
2005-08-04 17:40
2005.09.18
Запрос на объединенние таблиц под разными алиасами


14-1124382322
Vudu
2005-08-18 20:25
2005.09.18
Opera и глюк





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