Форум: "Начинающим";
Текущий архив: 2006.11.05;
Скачать: [xml.tar.bz2];
ВнизКак удалить объект из дочернего потока Найти похожие ветки
← →
Priest © (2006-10-18 14:38) [0]Есть объект. Я хочу, чтобы определёныый момент он был удалён из дочернего потока. Если делать через Free, то получается что объект выпоняет свой метод и удаляется в середине выполнения. Из-за этого возникают ошибки. Через PostMessage я тоже не могу, так как объект закончит свой метод, а потом удалится. А мне нужно имено в середине метода. Как осуществить сабж?
← →
i-am-vladko © (2006-10-18 14:52) [1]а что за объект?
← →
Priest © (2006-10-18 14:55) [2]Ну это мой класс. Я хочу чтобы дочерний поток мог удалить объект в тот момент, когда он выполняет метод
← →
i-am-vladko © (2006-10-18 14:59) [3]а почему именно в середине метода ????
← →
Сергей М. © (2006-10-18 15:01) [4]Галиматьища.
Код ?
← →
Priest © (2006-10-18 15:02) [5]ну в момент выполнения. может и в начале. а может и в самом конце. вся проблема в том, что метод ещё не выполнился. я удаляю объект, а метод продолжает своё выполнение и обращается к уже не существующим данным
← →
i-am-vladko © (2006-10-18 15:05) [6]че ето за метод такой???
← →
Сергей М. © (2006-10-18 15:15) [7]Галиматьища
← →
Priest © (2006-10-18 15:16) [8]Есть примерно 20 методов. В начале метода блокируется общая критическая секция. И где то она не освобождается. Я хочу чтобы мой внешний поток определил повисший компонент и его удалил.
← →
i-am-vladko © (2006-10-18 15:17) [9]а виснет-то он почему?
← →
Сергей М. © (2006-10-18 15:19) [10]
> где то она не освобождается.
Да, есть повод определить это как ошибку программирования.
> очу чтобы мой внешний поток определил повисший компонент
> и его удалил
Галиматьища несусветная.
← →
Priest © (2006-10-18 15:20) [11]Поясню псевдокодом
Вот мой метод
Enter //Вход в крит. секцию
try
//Оповещение ком+ подписок
//вот здесь код может повиснуть.
finally
Leave();//Освобождение секции
end;
Я хочу определить что секция очень долго заблокирована. У меня есть идентификатор потока в котором заблокирована секция. Я хочу этот поток прибить..
← →
i-am-vladko © (2006-10-18 15:23) [12]почему секция виснет???
← →
Сергей М. © (2006-10-18 15:25) [13]
> Priest © (18.10.06 15:20) [11]
> хочу этот поток прибить
см. TerminateThread()
> хочу определить что секция очень долго заблокирована
см. TryEnterCriticalSection ()
← →
Priest © (2006-10-18 15:30) [14]Секция виснет потому, что в момент оповещения подписок COM+ подвисает метод оповещения. Происходит это примерно 1 раз за 5 часов. Возможно что СОМ+ пытается оповерстить подписку компа, который аварийно завершился. А может просто проблемы с сетью и тот комп не получает сообщения....Может ещё что то. Но виснет оповещение подписок. Для каждого клиенто создаётся отдельный экземпляр серверного объекта. Поэтому если повисло оповещение, то мне уже не нужен данный объект. Я хочу его уничтожить. К тому же он держит секцию. Вот я и хочу удалить его.
← →
Сергей М. © (2006-10-18 15:32) [15]Отладчик тебе на что дан ?
← →
Priest © (2006-10-18 15:36) [16]Ну я описал где ошибка в [14]. Виснет на оповещении подписки
← →
i-am-vladko © (2006-10-18 15:39) [17]Заверши етот метод. А потом и объект удаляй.
← →
Сергей М. © (2006-10-18 15:40) [18]И ?
Что говорит отладчик о деталях причины "виса" ?
← →
Priest © (2006-10-18 15:49) [19]см. TerminateThread()
Юзал. Всё равно метод продолжается до конца
> хочу определить что секция очень долго заблокирована
см. TryEnterCriticalSection ()
На самом деле у меня не секция. А Эвент. Но работает так же. И получается у меня что я получаю свою секцию и начинаю выполнять код. А вот сам код что то делает.
>>Что говорит отладчик о деталях причины "виса" ?
На уровне CPU не дошёл. Слишком уж кода там много получается. А когда pause нажимает, то сама ИДЕ уже не отвечает :(
Самое интересное то, что если оставить экземпляр серверного объекта, освободить секцию в моём дочеренм потоке, что через некоторое время (минут 15-20) все подписки успешно оповещаются и приложение работает дальше
← →
Сергей М. © (2006-10-18 15:55) [20]Удалено модератором
← →
i-am-vladko © (2006-10-18 15:56) [21]давай код
← →
Priest © (2006-10-18 16:13) [22]Вот вырезал код с секцией
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.
Но код я увидел :(
← →
Сергей М. © (2006-10-18 16:16) [23]О боже ....
> Priest
Где ты этого безобразия нахватался ?! .. У Архангельского ? ... У Кариха ?...
← →
i-am-vladko © (2006-10-18 16:19) [24]Удалено модератором
← →
i-am-vladko © (2006-10-18 16:22) [25]> CS.Enter();
виснет здесь, чтоли?
gg=))
← →
Priest © (2006-10-18 16:23) [26]Что не так? ТАм где виснет я написал sleep
← →
i-am-vladko © (2006-10-18 16:24) [27]CurrThread := GetCurrentThreadId();
- это мне недавно проясняли ))) посмотри на форуме
← →
Priest © (2006-10-18 16:25) [28]Удалено модератором
← →
i-am-vladko © (2006-10-18 16:25) [29]ДА ВОБЩЕМ
ВСЕ НЕ ТАК
← →
Сергей М. © (2006-10-18 16:26) [30]
> Priest
Галиматьища полная.
ты где этот код содрал ?)
← →
Priest © (2006-10-18 16:27) [31]>>CurrThread := GetCurrentThreadId();
А ссылку можно.
← →
i-am-vladko © (2006-10-18 16:27) [32]а это еще че?
if Thread.Suspended then
Thread.Resume();
Thread.Terminate();
← →
Priest © (2006-10-18 16:36) [33]Нашёл я твою ветку
The GetCurrentThread function returns a pseudohandle for the current thread.
HANDLE GetCurrentThread(VOID)
А я юзаю
The GetCurrentThreadId function returns the thread identifier of the calling thread.
DWORD GetCurrentThreadId(VOID)
>>if Thread.Suspended then
Thread.Resume();
Вот помощь
Terminate sets the thread’s Terminated property to true, signaling that the thread should be terminated as soon as possible.
For Terminate to work, the thread"s Execute method and any methods that Execute calls should check Terminated periodically and exit when it"s true.
Если поток остановлен, то его метод Execute не будет выполняться и следовательно, негде проверять флаг Terminated
← →
Priest © (2006-10-18 16:44) [34]Ладно с самого начала. Мне нужна критическая секция, в которую можно было входить рекурсивно и при этом она ожидалась не вечно, а определеённое время. Для этого я ввёл класс TPxCriticalSection.
Что в классе не так?
При этом получается так, что некоторые потоки входят в критическую секцию, но уже не выходят за предельно допустимое время. Поэтому я запускаю дочерний поток, который "убивает" тот поток, который завладел секцией.
Что тут не так?
← →
Сергей М. © (2006-10-18 16:49) [35]
> Что тут не так?
Здесь все не так.
Начиная с "входить рекурсивно .. в критическую секцию", ибо это полная галиматья.
← →
Priest © (2006-10-18 16:52) [36]Почему ерунда? Вот у меня есть метод, часть вычислений выполняется в крит секции. В этой части вызывается другой метод, а в нём тоже вход в критич. секцию. Вы предлагаете везде проверять не вошли ли мы в секцию?
А смысл? Если внутрений метод может вызываться сам и ему нужна секция и внутри другого метода, где тоже нужна секция
← →
Priest © (2006-10-18 16:54) [37]Я имею ввиду вход из одного потока в критическую секцию несколько раз типа
Enter
try
Enter
try
finally
Leave
end
finally
Leave
end
Что тут не так?
← →
Пусик © (2006-10-18 17:50) [38]
> Priest © (18.10.06 16:44) [34]
> Ладно с самого начала. Мне нужна критическая секция, в которую
> можно было входить рекурсивно и при этом она ожидалась не
> вечно, а определеённое время. Для этого я ввёл класс TPxCriticalSection.
>
Один и тот же поток и так может входить в критическую секцию сколько угодно раз.
Для этого нет необходимости свой класс писать.
← →
Сергей М. © (2006-10-19 08:27) [39]
> Priest © (18.10.06 16:52) [36]
Система ведет подсчет aquire/release каждой крит.секции.
Успешный "вход" потока в секцию (aquire) приводит к увеличению внутр.сч-ка на 1, "выход" потока из секции (realease) сопровождается соотв-но уменьшением сч-ка на 1.
Любой другой поток того же процесса не сможет осуществить "вход" в секцию до тех пор пока ее сч-к > 0, т.е. если поток А выполнил два aquire и всего один release перед тем как "умереть", ни один другой поток того же процесса не сможет с этого момента войти в секцию.
← →
Priest © (2006-10-19 09:18) [40]Пусик, Сергей М.
Да знаю я это. Проблема в том, что стандартная реализация секции предпологает ожидание критической секции в aquire бесконечно долго. А мне нужно чтобы ждало определённое время. Поэтому я использовал эвент. Он позволяет ожидать заданое время. Но он не позволяет захватить его дважды из одного потока. Поэтому я изменил стандартную реализацию
Страницы: 1 2 вся ветка
Форум: "Начинающим";
Текущий архив: 2006.11.05;
Скачать: [xml.tar.bz2];
Память: 0.57 MB
Время: 0.092 c