Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Как удалить объект из дочернего потока


Страницы:   1 2 3

Priest ©   (2006-10-18 14:38:00) 

Есть объект. Я хочу, чтобы определёныый момент он был удалён из дочернего потока. Если делать через Free, то получается что объект выпоняет свой метод и удаляется  в середине выполнения. Из-за этого возникают ошибки. Через PostMessage я тоже не могу, так как объект закончит свой метод, а потом удалится. А мне нужно имено в середине метода. Как осуществить сабж?


i-am-vladko   (2006-10-18 16:22:00) [21]

> CS.Enter();
виснет здесь, чтоли?
gg=))


i-am-vladko   (2006-10-18 16:19:00) [22]

Удалено модератором


Сергей М.   (2006-10-18 16:16:00) [23]

О боже ....


> Priest


Где ты этого безобразия нахватался ?! .. У Архангельского ? ... У Кариха ?...


Priest   (2006-10-18 16:13:00) [24]

Вот вырезал код с секцией

program Project1;

{$APPTYPE CONSOLE}

uses
 madExcept,
 madLinkDisAsm,
 madListHardware,
 madListProcesses,
 madListModules,
 SysUtils, SyncObjs, classes,windows,DateUtils;

type  
 TPxCriticalSection = class;
 TPxCriticalSectionThread = class(TThread)
 private
   FIdenty: string;
   FLocker: string;
   FLockThread: Integer;
   FLockTime: TDateTime;
     Name: string;
   Section: TPxCriticalSection;
   procedure TestTimeOut;
 protected
   procedure SetIdenty(const Value: string);
   procedure SetLocker(const Value: string);
   procedure SetLockThread(const Value: Integer);
   procedure SetLockTime(const Value: TDateTime);
 public
   constructor Create(ASection: TPxCriticalSection);
   procedure Execute; override;
   procedure Resume;
   procedure Suspend;
   property Identy: string read FIdenty write SetIdenty;
   property Locker: string read FLocker write SetLocker;
   property LockThread: Integer read FLockThread write SetLockThread;
   property LockTime: TDateTime read FLockTime write SetLockTime;
 end;

 TPxCriticalSection = class(TSimpleEvent)
 private
   FName: string;
 protected
   LastIdentifier: string;
   LastLocker: string;
   LastLockThread: Cardinal;
   LockCount: Integer;
   Thread: TPxCriticalSectionThread;
 public
   constructor Create(AName: string); virtual;
   destructor Destroy; override;
   procedure BeforeTerminatedLockedThread; virtual;
   function Enter(Identifier: string = '0'; WaitTime: Integer = 120000): Boolean;
   procedure Leave(IsEnter: Boolean);
 published
   property Name: string read FName;
 end;

type
 TDefault = class(TObject)
 public
   procedure SameMethod;
 end;

procedure TDefault.SameMethod;
var
CS:TPxCriticalSection;
begin
CS:=TPxCriticalSection.Create('Sec');
CS.Enter();
sleep(60000);
writeln('Эту строку не увидишь ТЫ!')
end;

{ TCriticalSection }

constructor TPxCriticalSection.Create(AName: string);
begin
 inherited Create;
 FName := AName;
 SetEvent;
 Thread := TPxCriticalSectionThread.Create(self);
end;

destructor TPxCriticalSection.Destroy;
begin
 if Thread.Suspended then
   Thread.Resume();
 Thread.Terminate();
 inherited;
end;

procedure TPxCriticalSection.BeforeTerminatedLockedThread;
begin
//Ничего не делать в базовом классе
end;

function TPxCriticalSection.Enter(Identifier: string = '0'; WaitTime: Integer =
   120000): Boolean;
var
 CurrThread: Cardinal;
begin
 //Возможно что тот же самый поток
 CurrThread := GetCurrentThreadId();

 if CurrThread = LastLockThread then
   begin
     Inc(LockCount);
     Result := True
   end
 else
   begin
     if WaitFor(WaitTime) = wrSignaled then
       begin
         ResetEvent();
         LockCount := 1;
         Result := True;
//          LastLocker := GetCurrentCallStack(True);
         LastIdentifier := Identifier;
         LastLockThread := CurrThread;
         with Thread do
           begin
             Locker := LastLocker;
             LockThread := LastLockThread;
             Identy := LastIdentifier;
             LockTime := Now();
             Resume;
           end; //with
       end //if WaitFor(WaitTime) = wrSignaled then
     else
       begin
         Result := False;
//          SendDebug('Попытка получить доступ к заблокированной секции из ' + Name +
//            '[' + LastIdentifier + ']' + #13#10 + GetCurrentCallStack());
//          SendDebug('Секция ранее заблокирована в ' + Name + #13#10 + LastLocker);
         raise Exception.Create(' секция забл-на ' +
           Name + #13#10 {+ GetCurrentCallStack(True)}+ #13#10 +
           'Она з-на в ' + LastLocker);
       end;
   end; //else if CurrThread=LastLockThread then
end;

procedure TPxCriticalSection.Leave(IsEnter: Boolean);
begin
{  inherited Release;
  SendDebug('Освобождена секция '+Name+#13#10+
  StackTrace(True, True, True, nil, nil, true, true, 0, 0,
       nil, nil, nil, nil, nil, 0, True, false, nil, nil, nil, nil,
       nil, nil, true));}
 if IsEnter and (GetCurrentThreadId()=LastLockThread) then
   begin
     Dec(LockCount);
     if LockCount = 0 then
       begin
         Thread.Suspend;
         LastLocker := '';
         LastLockThread := 0;
         SetEvent();
       end;
   end; //if IsEnter then
end;

constructor TPxCriticalSectionThread.Create(ASection: TPxCriticalSection);
begin
 inherited Create(True);
 FreeOnTerminate := True;
 Section := ASection;
 Name := Section.Name;
end;

procedure TPxCriticalSectionThread.Execute;
begin
 while true do
   begin
     TestTimeOut;
   //Synchronize(TestTimeOut);
     sleep(1000);
   end; // while true
end;

procedure TPxCriticalSectionThread.Resume;
begin
 if Suspended then
   inherited Resume();
end;

procedure TPxCriticalSectionThread.SetIdenty(const Value: string);
begin
 if FIdenty <> Value then
   begin
     FIdenty := Value;
   end;
end;

procedure TPxCriticalSectionThread.SetLocker(const Value: string);
begin
 if FLocker <> Value then
   begin
     FLocker := Value;
   end;
end;

procedure TPxCriticalSectionThread.SetLockThread(const Value: Integer);
begin
 if FLockThread <> Value then
   begin
     FLockThread := Value;
   end;
end;

procedure TPxCriticalSectionThread.SetLockTime(const Value: TDateTime);
begin
 if FLockTime <> Value then
   begin
     FLockTime := Value;
   end;
end;

procedure TPxCriticalSectionThread.Suspend;
begin
 if not Suspended then
   inherited Suspend;
end;

procedure TPxCriticalSectionThread.TestTimeOut;
begin
 if (MilliSecondsBetween(Now(), LockTime) > 30000) then
   begin
//      SendDebug('Повис поток в ' + Name + '[' + Identy + ']' +
//        ' который заблокирован в ' + #13#10 +     Locker);

     //Оповещаем класс
     Section.BeforeTerminatedLockedThread();
     TerminateThread(LockThread, 0);
     Section.SetEvent();
   end;
end;

var
D:TDefault;
begin
D:=TDefault.Create;
D.SameMethod;
D.Free;
end.

Но код я увидел :(


i-am-vladko   (2006-10-18 15:56:00) [25]

давай код


Сергей М.   (2006-10-18 15:55:00) [26]

Удалено модератором


Priest   (2006-10-18 15:49:00) [27]

см. TerminateThread()

Юзал. Всё равно метод продолжается до конца

> хочу определить что секция очень долго заблокирована
см. TryEnterCriticalSection ()
На самом деле у меня не секция. А Эвент. Но работает так же. И получается у меня что я получаю свою секцию и начинаю выполнять код. А вот сам код что то делает.

>>Что говорит отладчик о деталях причины "виса" ?
На уровне CPU не дошёл. Слишком уж кода там много получается. А когда pause нажимает, то сама ИДЕ уже не отвечает :(

Самое интересное то, что если оставить экземпляр серверного объекта, освободить секцию в моём дочеренм потоке, что через некоторое время (минут 15-20) все подписки успешно оповещаются и приложение работает дальше


Сергей М.   (2006-10-18 15:40:00) [28]

И ?

Что говорит отладчик о деталях причины "виса" ?


i-am-vladko   (2006-10-18 15:39:00) [29]

Заверши етот метод. А потом и объект удаляй.


Priest   (2006-10-18 15:36:00) [30]

Ну я описал где ошибка в [14]. Виснет на оповещении подписки


Сергей М.   (2006-10-18 15:32:00) [31]

Отладчик тебе на что дан ?


Priest   (2006-10-18 15:30:00) [32]

Секция виснет потому, что в момент оповещения подписок COM+ подвисает метод оповещения. Происходит это примерно 1 раз за 5 часов. Возможно что СОМ+ пытается оповерстить подписку компа, который аварийно завершился. А может просто проблемы с сетью и тот комп не получает сообщения....Может ещё что то. Но виснет оповещение подписок. Для каждого клиенто создаётся отдельный экземпляр серверного объекта. Поэтому если повисло оповещение, то мне уже не нужен данный объект. Я хочу его уничтожить. К тому же он держит секцию. Вот я и хочу удалить его.


Сергей М.   (2006-10-18 15:25:00) [33]


> Priest ©   (18.10.06 15:20) [11]


> хочу этот поток прибить


см. TerminateThread()


> хочу определить что секция очень долго заблокирована


см. TryEnterCriticalSection ()


i-am-vladko   (2006-10-18 15:23:00) [34]

почему секция виснет???


Priest   (2006-10-18 15:20:00) [35]

Поясню псевдокодом
Вот мой метод

 Enter //Вход в крит. секцию
try
//Оповещение ком+ подписок
//вот здесь код может повиснуть.

finally
Leave();//Освобождение секции
end;

Я хочу определить что секция очень долго заблокирована. У меня есть идентификатор потока в котором заблокирована секция. Я хочу этот поток прибить..


Сергей М.   (2006-10-18 15:19:00) [36]


> где то она не освобождается.


Да, есть повод определить это как ошибку программирования.


> очу чтобы мой внешний поток определил повисший компонент
>  и его удалил


Галиматьища несусветная.


i-am-vladko   (2006-10-18 15:17:00) [37]

а виснет-то он почему?


Priest   (2006-10-18 15:16:00) [38]

Есть примерно 20 методов. В начале метода блокируется общая критическая секция. И где то она не освобождается. Я хочу чтобы мой внешний поток определил повисший компонент  и его удалил.


Сергей М.   (2006-10-18 15:15:00) [39]

Галиматьища


i-am-vladko   (2006-10-18 15:05:00) [40]

че ето за метод такой???


Страницы:   1 2 3

Наверх

Титульная страница Поиск, карта сайта Написать письмо