![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Неправильная работа потока [D7, WinXP]
NeoMaster © (2005-07-25 11:31:00)Создаю сервис. Сервис создан для слежения за изменением файловой системы. Саму процедуру обработки слежения помещаю в отдельный поток в методу Execute. Создаю поток
NCThread:=TNCThread.Create(False);Всё хорошо компилится и запускается, но поток выполняется только один раз. Так как в файл записывается только один(самый первый) изменённый файл. Вот сокращённый код потока:
...
i: integer;
...
i:=0;
...
Procedure TNCThread.execute;
var
hDir : THandle;
lpBuf : Pointer;
Ptr : Pointer;
cbReturn : Cardinal;
FileName : PWideChar;//Имя файла
iniFile: TIniFile;
begin
iniFile:=TiniFile.Create('1.ini')
hDir := CreateFile ('C:\',GENERIC_READ,FILE_SHARE_READ or FILE_SHARE_WRITE or FILE_SHARE_DELETE,nil,OPEN_EXISTING,FILE_FLAG_BACKUP_SEMANTICS,0);
if hDir = INVALID_HANDLE_VALUE
then begin ShowMessage(SysErrorMessage(GetLastError)); exit; end;
GetMem(lpBuf,BUF_SIZE);
Repeat
ZeroMemory(lpBuf,BUF_SIZE);
if not ReadDirectoryChangesW(hDir,lpBuf,BUF_SIZE,true, FILE_NOTIFY_CHANGE_FILE_NAME + FILE_NOTIFY_CHANGE_DIR_NAME + FILE_NOTIFY_CHANGE_LAST_WRITE + FILE_NOTIFY_CHANGE_ATTRIBUTES + FILE_NOTIFY_CHANGE_SIZE + FILE_NOTIFY_CHANGE_LAST_ACCESS + FILE_NOTIFY_CHANGE_CREATION + FILE_NOTIFY_CHANGE_SECURITY,@cbReturn,nil,nil) then Break;
Ptr:=lpBuf;
repeat
GetMem(FileName,PFileNotifyInformation(Ptr).FileNameLength+2);
ZeroMemory(FileName,PFileNotifyInformation(Ptr).FileNameLength+2);
lstrcpynW(FileName,PFileNotifyInformation(Ptr).FileName, PFileNotifyInformation(Ptr).FileNameLength div 2+1);
i:=i+1;
iniFile.WriteString('MAIN'.'NAME' + IntToStr(i), FileName);
FreeMem(FileName);
until false;
until false;
FreeMem(lpBuf);
End;
NeoMaster (2005-07-29 11:12:00) [1]Вообще-то там структуры try..finally. Но всё равно спасибо всем - ошибку свою я понял. Всё работает(тьфу,тьфу,тьфу через левое плечо). Сейчас код оптимизировать пойду.
tesseract (2005-07-29 10:02:00) [2]>>> Если начнет кушать память, Handl'ы, прочие системные объекты- сервер долго не протянет.
Не кушай память и прочие системные объекты Try.. except служит для того чтобы обработать ошибку, а не избавится от них.
Slym (2005-07-28 05:27:00) [3]tesseract © (27.07.05 20:59) [13]
Слишком много try except не бывает... Особенно в постоянно и интенсивно работающем приложении (сервисе)...
Если начнет кушать память, Handl'ы, прочие системные объекты- сервер долго не протянет
tesseract (2005-07-27 20:59:00) [4]>> GetMem(lpBuf,BUF_SIZE); , FreeMem(lpBuf,BUF_SIZE); - несуразность BUF_SIZE DELPHI проигнорирует NEW и DISPOSE с какого-то перепоя в D7 вызывают меньше проблем.
Слишком много try except.
После сбоя CreteFile Вызов CloseHandle вызовет ошибку Delphi - отключается в настройках дебаггера.
@cbReturn - точно а может лучше без собачки (Не уверен но подозреваю)
Digitman (2005-07-26 15:47:00) [5]
> Кстати этот код очень стабильно и ровно работает в обычном
> exe приложение
врешь.
галиматьи и несуразностей в этом коде - хоть отбавляй.
Digitman (2005-07-26 15:34:00) [6]
> приходится методом проб и ошибок
в станд.справке есть инф-ция по отладке сервисов, написанных в делфи, средствами встр.отладчика Делфи
NeoMaster (2005-07-26 12:56:00) [7]В проекте я не вывожу результаты сразу в ini файл, а здесь для примера использовал эту возможность. Но для Piter специально допишу:)
...
iniFile.Free;
...
Толку всё равно нет. Сначала сделаю этот сервис работоспособным, а потом уже будет оптимизация.
Для Slym:
Это мой первый проект-сервис. Соответствующей литературы не нашёл. Вот и приходится методом проб и ошибок. Кстати этот код очень стабильно и ровно работает в обычном exe приложение(сейчас мне и необходимо перегнать приложение в сервис). Посмотрел твой код. Хоть что начало работать, но реальных изменений сервис так и не находит, а выводит сообщение только об одном и том же изменившемся файле. Изменяешь кокой-либо файл, а сервис выводит, что изменился совершенно другой файл. Но всё равно я ещё поколдую.
Slym (2005-07-26 05:49:00) [8]ПРЕДУПРЕЖДЕНИЕ: Код не проверял на работоспособность.
const BUF_SIZE=4096;
var
i:integer;
IniFile: TIniFile;
hDir:THandle;
lpBuf : Pointer;
FNI : PFileNotifyInformation;
cbReturn : Cardinal;
FileName : WideString;//Имя файла
begin
i:=0;
IniFile:=TiniFile.Create('1.ini');
try
hDir:=CreateFile ('C:\',GENERIC_READ,FILE_SHARE_READ or FILE_SHARE_WRITE or FILE_SHARE_DELETE,nil,OPEN_EXISTING,FILE_FLAG_BACKUP_SEMANTICS,0);
if hDir = INVALID_HANDLE_VALUE then
RaiseLastOSError;
try
GetMem(lpBuf,BUF_SIZE);
try
while not Terminated do
begin
ZeroMemory(lpBuf,BUF_SIZE);
if not ReadDirectoryChangesW(hDir,lpBuf,BUF_SIZE,true, FILE_NOTIFY_CHANGE_FILE_NAME + FILE_NOTIFY_CHANGE_DIR_NAME + FILE_NOTIFY_CHANGE_LAST_WRITE + FILE_NOTIFY_CHANGE_ATTRIBUTES + FILE_NOTIFY_CHANGE_SIZE + FILE_NOTIFY_CHANGE_LAST_ACCESS + FILE_NOTIFY_CHANGE_CREATION + FILE_NOTIFY_CHANGE_SECURITY,@cbReturn,nil,nil) then
RaiseLastOSError;
if cbReturn=0 then continue;
FNI:=lpBuf;
repeat
SetString(FileName,FNI.FileName,FNI.FileNameLength);
IniFile.WriteString('MAIN','NAME'+IntToStr(i), FileName);
Inc(i);
Inc(FNI,FNI.NextEntryOffset);
until FNI.NextEntryOffset<>0;
end;
finally
FreeMem(lpBuf,BUF_SIZE);
end;
finally
CloseHandle(hDir);
end;
finally
IniFile.Free;
end;
end;
Slym (2005-07-26 05:27:00) [9]Вообще код ужасный... С такими возможными утечками памяти и абсолютной необработкой искл. ситуаций сервисы писать нельзя.
ANB (2005-07-25 14:06:00) [10]
> Ptr:=lpBuf;
> repeat
> GetMem(FileName,PFileNotifyInformation(Ptr).FileNameLength+2);
> ZeroMemory(FileName,PFileNotifyInformation(Ptr).FileNameLength+2);
> lstrcpynW(FileName,PFileNotifyInformation(Ptr).FileName,
> PFileNotifyInformation(Ptr).FileNameLength div 2+1);
> i:=i+1;
> iniFile.WriteString('MAIN'.'NAME' + IntToStr(i), FileName);
> FreeMem(FileName);
> until false;
- вот сей кусок меня тоже определенно смущает. Про Free уже писали. А здесь я не вижу в упор условия для выхода из цикла. Да, и для выбора следующего файла из списка тоже. Может не внимательно смотрел.
Piter (2005-07-25 13:29:00) [11]NeoMaster © (25.07.05 13:13) [4]
мой текст:
Но нигде его не закрываешь:
iniFile.Free
ты значит проигнорировал. Молодец!
Digitman (2005-07-25 13:17:00) [12]
> Поток создаю в процедуре ServiceStart
какие еще события сервиса обрабатываешь ?
если создаешь поток в обычном (не сервисном) приложении, результаты те же ? если те же, какие ты принял меры по отладке приведенного кода в обычном приложении, прежде чем переносить его в сервис-приложение ?
NeoMaster (2005-07-25 13:13:00) [13]Не помогает. Без разницы, что
Repeat...Until, чтоWhile true do, чтоwhile not Terminated do. Всё равно ловит только первое ищменение. Поток создаю в процедуре ServiceStart. А бесконечный цикл - это для примера.
Kolan (2005-07-25 12:01:00) [14]Чтобы процедура выполнялась в цикле надо делать так
ВExecute:
while notTerminated do
SomeWork();
А код вSomeWork...
Digitman (2005-07-25 11:57:00) [15]
> Создаю поток NCThread:=TNCThread.Create(False)
в каком месте ?
Piter (2005-07-25 11:47:00) [16]1) Ну например ты создаешь TIniFile:
iniFile:=TiniFile.Create('1.ini')
Но нигде его не закрываешь:
iniFile.Free
2) потоки с бесконечными циклами... это нечто :)
А почему использовать repeat, а не:
while true do ...
? :)