Rambler's Top100
"Knowledge itself is power"
F.Bacon
Поиск | Карта сайта | Помощь | О проекте | ТТХ  
 Круглый стол
  
Правила КС
>> Настройки

Фильтр вопросов
>> Новые вопросы
отслеживать по
>> Новые ответы

Избранное

Страница вопросов
Поиск по КС


Специальные проекты:
>> К л ю к в а
>> Г о л о в о л о м к и

Вопрос №

Задать вопрос
Off-topic вопросы

Помощь

 
 К н и г и
 
Книжная полка
 
 
Библиотека
 
  
  
 


Поиск
 
Поиск по КС
Поиск в статьях
Яndex© + Google©
Поиск книг

 
  
Тематический каталог
Все манускрипты

 
  
Карта VCL
ОШИБКИ
Сообщения системы

 
Форумы
 
Круглый стол
Новые вопросы

 
  
Базарная площадь
Городская площадь

 
   
С Л С

 
Летопись
 
Королевские Хроники
Рыцарский Зал
Глас народа!

 
  
ТТХ
Конкурсы
Королевская клюква

 
Разделы
 
Hello, World!
Лицей

Квинтана

 
  
Сокровищница
Подземелье Магов
Подводные камни
Свитки

 
  
Школа ОБЕРОНА

 
  
Арсенальная башня
Фолианты
Полигон

 
  
Книга Песка
Дальние земли

 
  
АРХИВЫ

 
 

Сейчас на сайте присутствуют:
 
  
 
Во Флориде и в Королевстве сейчас  05:09[Войти] | [Зарегистрироваться]
Ответ на вопрос № 61596

24-04-2008 23:11
Добрый день.Подскажите пожалуйста,как сделать,чтобы при закрытии программы программа снималась из памяти,наподобие того,как ее снимает Диспетчер задач
Заранее спасибо

[+] Добавить в избранные вопросы

Отслеживать ответы на этот вопрос по RSS

Ответы:


Уважаемые авторы вопросов! Большая просьба сообщить о результатах решения проблемы на этой странице.
Иначе, следящие за обсуждением, возможно имеющие аналогичные проблемы, не получают ясного представления об их решении. А авторы ответов не получают обратной связи. Что можно расценивать, как проявление неуважения к отвечающим от автора вопроса.

10-11-2008 04:23
Кстати, по поводу кнопки на панели задач: What's with those blank taskbar buttons that go away when I click on them?

01-05-2008 01:12 | Комментарий к предыдущим ответам
надо искать ошибку в программе
А с этим никто и не спорит :-)

30-04-2008 13:42 | Комментарий к предыдущим ответам
По-моему, моего телепатора никто не послушал. А ведь мне кажется, он правильно мыслит. То есть надо искать ошибку в программе, что она не освобождает, куда суется, что процесс остается висеть. Вот Word например, если кто-то им попользуется, а потом корректно не освободит, то он остается висеть в памяти. Вот что с ним делать? Ответ - правильно писать программы и тщательнее отлаживать.

30-04-2008 07:20 | Комментарий к предыдущим ответам
С событиями понятно - в критической секции для ожидания использует событие (Event). Проверка захвата критической секции осуществляется функцией EnterCriticalSection. При необходимости, она "переинициализирует" критическую секцию.
Если использовать напрямую Event, то это сделать некому.

30-04-2008 07:09 | Комментарий к предыдущим ответам
Да в точности та же ситуация, о которой мы говорим, только замените критические секции на любой другой объект синхронизации.
Любой? А если взять мьютекс?

30-04-2008 06:45 | Комментарий к предыдущим ответам
Во, у меня ещё остался тестовый код:

library Project1;

uses
  Windows, SysUtils;

var

//  Test: TRTLCriticalSection;

  Test: THandle;

  NeverHappen: Boolean;

procedure MyDLLProc(Reason: Integer);
begin
  if (Reason = DLL_PROCESS_DETACH) or (Reason = DLL_THREAD_DETACH) then
  begin
    OutputDebugString('Ready?');

    // EnterCriticalSection(Test);

    if WaitForSingleObject(Test, INFINITE) <> WAIT_OBJECT_0 then
      OutputDebugString(PChar(SysErrorMessage(GetLastError)));

    OutputDebugString('Passed');
    // Сюда мы доходим только в случае критической секции
    OutputDebugString('Exit from DllProc');
  end;
end;

function TestThread(P: DWord): DWord; stdcall;
var
  X: Integer;
begin
  OutputDebugString('Before Lock');

  // EnterCriticalSection(Test);

  if WaitForSingleObject(Test, INFINITE) <> WAIT_OBJECT_0 then
    OutputDebugString(PChar(SysErrorMessage(GetLastError)));

  OutputDebugString('Locked');
  SetThreadPriority(GetCurrentThread, THREAD_PRIORITY_LOWEST);
  X := 0;
  while not NeverHappen do
    X := X + 1;
  OutputDebugString('Oops!');
  Result := X;
end;

procedure DoIt;
var
  TID: DWord;
begin

//  InitializeCriticalSection(Test);

  Test := CreateEvent(nil, False, True, nil);

  CreateThread(nil, 1024, @TestThread, nil, 0, TID);
  Sleep(1000);
end;

exports
  DoIt;

begin
  DLLProc := MyDLLProc;
end.



procedure DoIt; external 'Project1.dll';

procedure TForm1.Button1Click(Sender: TObject);
begin
  OutputDebugString('Before DoIt');
  DoIt;
  OutputDebugString('Before ExitProcess');
  ExitProcess(1);
end;



Суть та же: если в приложении имеются работающие потоки, вызывать ExitProcess не безопасно, т.к. может возникнуть deadlock из-за того, что поток может быть прерван в то время, как он держит блокировку.

30-04-2008 06:38 | Комментарий к предыдущим ответам
Да в точности та же ситуация, о которой мы говорим, только замените критические секции на любой другой объект синхронизации.

30-04-2008 05:43 | Комментарий к предыдущим ответам
Что значит "например"?
Хотел увидеть пример ситуации, когда эти объекты синхронизации могут вызвать взаимоблокировку при вызове ExitProcess.


30-04-2008 05:24 | Комментарий к предыдущим ответам
>>> Например.
Что значит "например"? Вы что, не знаете других объектов синхронизации, помимо критических секций? :)  События, например. Да и вообще любые объекты ядра, которые можно использовать с WaitForSingleObject.

30-04-2008 04:19 | Комментарий к предыдущим ответам
От себя замечу, что проблемы это не решает, т.к. во-первых, другие способы блокировки всё же приведут к блокировке процесса.
Например.

А во-вторых, вместо deadlock мы получаем, что глобальные ресурсы, которые были защищены критической секцией, во время ExitProcess оказываются в испорченном состоянии.
Поэтому в Windows Vista вместо имитации успешного захвата секции сразу вызывается NtTerminateProcess.

30-04-2008 04:15 | Комментарий к предыдущим ответам
Провёл проверку: действительно, критические секции во время ExitProcess не блокируются.
От себя замечу, что проблемы это не решает, т.к. во-первых, другие способы блокировки всё же приведут к блокировке процесса. А во-вторых, вместо deadlock мы получаем, что глобальные ресурсы, которые были защищены критической секцией, во время ExitProcess оказываются в испорченном состоянии.

30-04-2008 03:22
Огромное спасибо!Все заработало на ура

30-04-2008 03:17
http://blogs.msdn.com/cbrumme/archive/2003/08/20/51504.aspx

30-04-2008 02:17 | Комментарий к предыдущим ответам
2 BlackHole: а есть ссылка, где это почитать?
В описании ExitProcess http://msdn.microsoft.com/en-us/library/ms682658.aspx ничего такого нет.
В EnterCriticalSection http://msdn.microsoft.com/en-us/library/ms682608.aspx аналогично.

30-04-2008 01:26 | Комментарий к предыдущим ответам
Не исключён сценарий, когда поток останавливается TerminateThread в момент вызова GetMem (т.е. в момент блокировки менеджера памяти), а затем при DLL_PROCESS_DETACH происходит попытка освобождения памяти => мы получаем блокировку и повисание процесса при выходе.
Чтобы избежать блокировки на критической секции, захваченной другим потоком во время ExitProcess, в функцию EnterCriticalSection был добавлен код, обрабатывающий эту ситуацию.
Начиная с Windows XP EnterCriticalSection проверяет захвачена ли секция и, в случае если захвачена, сверяет идентификатор текущего потока с идентификатором захватчика.
Windows XP/Windows 2003: Вместо бесконечного ожидания, текущий поток назначается владельцем критической секции, так как если бы она была захвачена нормальным способом. Тем самым программа сможет продолжить выполнение вплоть до финального вызова NtTerminateProcess.
Но данное решение проблемы оказалось не очень безопасным. Поэтому в Windows Vista вместо имитации успешного захвата секции сразу вызывается NtTerminateProcess.

28-04-2008 03:27
2 VJ

А может стоило попытаться найти свою ошибку, из-за которой форма закрывается, а процесс остается? Нет?
 NS

28-04-2008 02:10 | Комментарий к предыдущим ответам
Конечной контрольный. Я сталкивался с таким, когда форма закрывается, а процесс остается.

Верю. А почему тогда не написали так:

procedure TForm1.Form1Close(Sender: TObject);
begin
  Application.Terminate;
  Application.Terminate;
end;


Вдруг первый вызов не сработает? ;-)

28-04-2008 00:53 | Комментарий к предыдущим ответам
>>>Контрольный ;-)
Конечной контрольный. Я сталкивался с таким, когда форма закрывается, а процесс остается.

27-04-2008 15:38 | Комментарий к предыдущим ответам
Нет, ExitProcess и TerminateProcess - существенно разные функции завершения процесса.

27-04-2008 15:31
Я не раз встречал такое со своим проектом, но при одних и тех же обстоятельствах.

Например, взять FIBDataset и сделать по умолчанию опцию FetchAll = True (порядка 500 записей). Взять Devrace SQL Monitor. При запуске проекта с запущенным SQL Monitor-ом проект нормально не выгружается.
Без SQL Monitor-а все отлично выгружается.

27-04-2008 15:04 | Комментарий к предыдущим ответам
А разве приведённый ниже код не сделает то же самое?

27-04-2008 11:58 | Комментарий к предыдущим ответам
>>> не проще ли вызвать ExitProcess
Кстати говоря, это не всегда может быть безопасно:
All of the threads in the process, except the calling thread, terminate their execution. The entry-point functions of all loaded dynamic-link libraries (DLLs) are called with DLL_PROCESS_DETACH. After all attached DLLs have executed any process termination code, this function terminates the current process, including the calling thread.
Т.е. при ExitProcess вызывается TerminateThread для каждого потока. Затем вызываются DLL с DLL_PROCESS_DETACH. Не исключён сценарий, когда поток останавливается TerminateThread в момент вызова GetMem (т.е. в момент блокировки менеджера памяти), а затем при DLL_PROCESS_DETACH происходит попытка освобождения памяти => мы получаем блокировку и повисание процесса при выходе.

26-04-2008 16:42 | Комментарий к предыдущим ответам
И тут самый простой способ:

var
HWND_P,HWND_Proc,pid:Cardinal;
begin
  HWND_P:=form1.handle;
  GetWindowThreadProcessId(HWND_P,pid);
  HWND_Proc := OpenProcess(PROCESS_TERMINATE, FALSE, pid);
  TerminateProcess(HWND_Proc,4);
end;


Граждане, если нужен суицид, не проще ли вызвать ExitProcess()?

25-04-2008 04:22
На счет топика от 25-04-2008 03:50. Не въехал в вопрос.

25-04-2008 04:22 | Комментарий к предыдущим ответам
Это точно бесполезно :) При закрытии главной формы Application.Terminate вызывается автоматически :)
Контрольный ;-)

25-04-2008 04:06
Я бы стал искать ошибку в первую очередь в OnClose, OnCloseQuery, OnDestroy главной формы, а также временно удалил бы все сторонние компоненты, в том числе и самопальные. Потом можно приступить к комментированию процедур, функций, методов, которые что-то занимают или создают (резервируют место в памяти, создают потоки и так далее) Когда найдете код, вызывающий ошибки, публикуйте его - будем думать.

25-04-2008 04:04 | Комментарий к предыдущим ответам
На закрытие главной формы поставить:
Application.Terminate


Это точно бесполезно :) При закрытии главной формы Application.Terminate вызывается автоматически :)

25-04-2008 03:50
То Автору

Создаете Form2 с 2-мя кнопками "Завершить процесс" и "Отменить". Украшаете фон каким нибудь текстом,
картинками. Далее объяснения вроде ненужны.

procedure TForm1.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
begin
  Form2.ShowModal;
  CanClose:=Form2.ModalResult;
end;


25-04-2008 03:33 | Комментарий к предыдущим ответам
Откуда вы это взяли? При принудительном уничтожении процесса просто не приходят Я вел речь о потоках, а не процессах. Пример. Приложение работает с СОМ-портом, используя отдельный поток, в котором никаких окон. Закрываем приложение нормальным Close-ом, а перед этим делаем TerminateThread потоку порта и закрытие самого порта - получаем "мертвое" окно в таскбаре. Которое впрочем при щелчке на нем (если не ошибаюсь - 10 лет прошло) пропадает.

25-04-2008 03:11 | Комментарий к предыдущим ответам
>>> В 9Х наличие кнопки на таскбаре означает, что какие-то ресурсы для этой задачи Винда дала, но обратно не получила.
Откуда вы это взяли? При принудительном уничтожении процесса просто не приходят HSHELL_WINDOWDESTROYED для его окон. В итоге в этом случае остаются «мертвые» кнопки на таскбаре.

25-04-2008 02:56 | Комментарий к предыдущим ответам
Не уловил связь между кнопкой на панели задач и стеком потока. В 9Х наличие кнопки на таскбаре означает, что какие-то ресурсы для этой задачи Винда дала, но обратно не получила. Висит в памяти исполняемый код (который то ли выполняется, то ли вообще не получает тиков) либо остались неосвобожденными ресурсы - без разницы! След от задачи остался - завершение некорректно. Множественный перезапуск сродни DOS-атаке, т.е. разрушение ОС по исчерпании ресурсов. Сильно сказал! :-)

25-04-2008 02:11
Вопрос автора вполне актуален был для меня недавно.
В программе есть таймер, который по срабатыванию должен выгрузить приложение (свое).
В программе рутинная работа с файлами и MemTable.
Так вот довольно сложно сделать Application.terminate из таймера когда "идет работа".

И тут самый простой способ:

var
HWND_P,HWND_Proc,pid:Cardinal;
begin
  HWND_P:=form1.handle;
  GetWindowThreadProcessId(HWND_P,pid);
  HWND_Proc := OpenProcess(PROCESS_TERMINATE, FALSE, pid);
  TerminateProcess(HWND_Proc,4);
end;


25-04-2008 02:09 | Комментарий к предыдущим ответам
2 NS
Читая пост Василия под "следами" после завершения программы при некорректной работе с потоками я подумал про то, что процесс остается висеть в памяти (по различным причинам).

К проблеме "кнопок на панели задач" мой пост [25-04-2008 00:49] не относится.
Этого не наблюдал и утверждать не могу.

25-04-2008 01:58
2 BlackHole
>>>Пример того, что после закрытия программы она остается висеть в списке процессов?

Я не знаю. Василий сказал
>>>Раньше (в 9Х виндах) если неграмотно завершать потоки - оставались "следы" от программ
Вы сказали
>>>И в w2k/хр такая ситуация возможна

Я не понял, о каких следах речь, вот и попросил пояснить. Ну не обязательно пример, хотя-бы описание ситуации. О кнопке на панели задач  Александр Алексеев уже сказал. Еще что-то?
 NS

25-04-2008 01:50 | Комментарий к предыдущим ответам
остается висеть в списке процессов
Ждем автора, т.к. телепатор именно это предположил при прочтении фразы чтобы при закрытии программы программа снималась из памяти.

25-04-2008 01:46 | Комментарий к предыдущим ответам
>>> после закрытия программы она остается висеть в списке процессов
Хм, значит программа ещё не завершилась. Скорее всего, либо она сама повисла в процессе обычного выхода, либо ей что-то мешает выйти, например:
TerminateProcess initiates termination and returns immediately. This stops execution of all threads within the process and requests cancellation of all pending I/O. The terminated process cannot exit until all pending I/O has been completed or canceled.

25-04-2008 01:40 | Комментарий к предыдущим ответам
Если поток, сгенеренный CreateThread-ом, завершить TerminateThread-ом (естественно после закрытия основной программы) - в ТаскБаре задача оставалась (в смысле панелька). Я так понял тогда - из-за некорректного высвобождения стека под поток.
Не уловил связь между кнопкой на панели задач и стеком потока.

При использовании TerminateThread стек потока не освобождается.
Он освобождается при завершении программы.

25-04-2008 01:33 | Комментарий к предыдущим ответам
2 NS
Можно пример?
Пример того, что после закрытия программы она остается висеть в списке процессов?

25-04-2008 01:27 | Комментарий к предыдущим ответам
>>> из-за некорректного высвобождения стека под поток.
Неверно. При завершении программы, вся занятая память освобождается. После закрытия программы никаких стеков потоков существовать не может. В этот момент единственное, что может остаться от программы - открытые описатели её процесса, которые можно использовать только для того, чтобы получить код завершения процесса.

>>> в ТаскБаре задача оставалась
И как это связано с самой программой? Просто Shell проморгал момент завершения программы и не убрал панельку.

25-04-2008 01:23 | Комментарий к предыдущим ответам
Причём тут потоки, если речь идёт о завершении процесса?

25-04-2008 01:19 | Комментарий к предыдущим ответам
Раньше (в 9Х виндах) если неграмотно завершать потоки - оставались "следы" Какие? Один пример...Если поток, сгенеренный CreateThread-ом, завершить TerminateThread-ом (естественно после закрытия основной программы) - в ТаскБаре задача оставалась (в смысле панелька). Я так понял тогда - из-за некорректного высвобождения стека под поток.

25-04-2008 01:10
>>>Раньше (в 9Х виндах) если неграмотно завершать потоки - оставались "следы"

Какие?

>>>И в w2k/хр такая ситуация возможна

Можно пример?
 NS

25-04-2008 00:49 | Комментарий к предыдущим ответам
2 Василий
что делают?
Я имел ввиду - сами завершаются при закрытии без какой-либо посторонней помощи.

Раньше (в 9Х виндах) если неграмотно завершать потоки - оставались "следы" от программ, а в w2k и хр - не видел этого.
И в w2k/хр такая ситуация возможна.

25-04-2008 00:42 | Комментарий к предыдущим ответам
Все добропорядочные программы так и делают. - что делают? То что написано в предыдущих постах??? В жизни этого не делал и вообще удивлен наличием этой проблемы. Раньше (в 9Х виндах) если неграмотно завершать потоки - оставались "следы" от программ, а в w2k и хр - не видел этого.

25-04-2008 00:28
Все добропорядочные программы так и делают.

25-04-2008 00:09
На закрытие главной формы поставить:

Application.Terminate


24-04-2008 23:55

var
HWND_P,HWND_Proc,pid:Cardinal;
begin
  HWND_P:=form1.handle;
  GetWindowThreadProcessId(HWND_P,pid);
  HWND_Proc := OpenProcess(PROCESS_TERMINATE, FALSE, pid);
  TerminateProcess(HWND_Proc,4);
end;


24-04-2008 23:36 | Вопрос к автору: запрос дополнительной информации
О_О
А что ж тогда программа сама делеат при своём закрытии, если не это?

Добавьте свое cообщение

Вашe имя:  [Войти]
Ваш адрес (e-mail):На Королевстве все адреса защищаются от спам-роботов
контрольный вопрос:
Жил-был у бабушки серенький КТО?
в качестве ответа на вопрос или загадку следует давать только одно слово в именительном падеже и именно в такой форме, как оно используется в оригинале.
Надоело отвечать на странные вопросы? Зарегистрируйтесь на сайте.
Тип сообщения:
Текст:
Жирный шрифт  Наклонный шрифт  Подчеркнутый шрифт  Выравнивание по центру  Список  Заголовок  Разделительная линия  Код  Маленький шрифт  Крупный шрифт  Цитирование блока текста  Строчное цитирование
  • вопрос Круглого стола № XXX

  • вопрос № YYY в тесте № XXX Рыцарской Квинтаны

  • сообщение № YYY в теме № XXX Базарной площади
  • обсуждение темы № YYY Базарной площади
  •  
     Правила оформления сообщений на Королевстве

    Страница избранных вопросов Круглого стола.
      
    Время на сайте: GMT минус 5 часов

    Если вы заметили орфографическую ошибку на этой странице, просто выделите ошибку мышью и нажмите Ctrl+Enter.
    Функция может не работать в некоторых версиях броузеров.

    Web hosting for this web site provided by DotNetPark (ASP.NET, SharePoint, MS SQL hosting)  
    Software for IIS, Hyper-V, MS SQL. Tools for Windows server administrators. Server migration utilities  

     
    © При использовании любых материалов «Королевства Delphi» необходимо указывать источник информации. Перепечатка авторских статей возможна только при согласии всех авторов и администрации сайта.
    Все используемые на сайте торговые марки являются собственностью их производителей.

    Яндекс цитирования