Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Начинающим";
Текущий архив: 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.044 c
15-1160720254
Dmitry_177
2006-10-13 10:17
2006.11.05
GUID Генерация уникального идентификатора


2-1161511329
Riply
2006-10-22 14:02
2006.11.05
EnumResourceTypes типы перебирает, но возвращает ошибку


15-1161064558
palva
2006-10-17 09:55
2006.11.05
Еще раз про пончик


15-1161020542
55_Ald
2006-10-16 21:42
2006.11.05
Как защитить dll от несанкционированного копирования?


15-1160483544
Nic
2006-10-10 16:32
2006.11.05
Олимпиада 1C





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