![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Как удалить объект из дочернего потока
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]че ето за метод такой???