![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Вопрос по потокам [XP]
petvv © (2009-03-17 07:52:00)Вот есть код:
constructor TMonDirThread.Create(aPath: String);
begin
inherited Create(True);
FreeOnTerminate := True;
FPath := aPath;
Self.Priority := tpHighest;
Resume;
end;
procedure TMonDirThread.UpdateLog;
var
s: string;
f: TextFile;
i: Integer;
begin
Result:=1;
KolStr:=0;
Full:= WideCharToString(Path)+'\'+WideCharToString(FileName);
CreateDBF();
AssignFile(f, Full);
Reset(f);
while not EOF(f) do
begin
ReadLn(f, s);
if Result=2 then
begin
// Сдесь получаем № и дату накладной
GetNom(s,12,20);
GetDat(s,21,31);
end;
Inc(Result,1);
end;
CloseFile(f);
//*************************************
// Получаем количество строк в файле
//*************************************
AssignFile(f, Full);
Reset(f);
while not EOF(f) do
begin
ReadLn(f, s);
Inc(KolStr,1);
end;
KolStr:=KolStr-4;
CloseFile(f);
//*******************
Result:=1;
AssignFile(f, Full);
Reset(f);
while not EOF(f) do
begin
ReadLn(f, s);
if Result>=5 then
begin
Form1.Table1.Append;
Form1.Table1.FieldByName('DATEN').AsDateTime:=StrToDateTime(ResultDat);
Form1.Table1.FieldByName('NOMN').AsString:=ResultNom;
//Отсюда начинается сама накладная
//Получим количество полей
GetFields(s, Length(s));
end;
Inc(Result,1);
end;
CloseFile(f);
DeleteFile(Full);
Form1.Table1.Active:=False;
end;
procedure TMonDirThread.Execute;
Type PFileNotifyInformation=^TFileNotifyInformation;
TFileNotifyInformation=packed record
NextEntryOffset:dword;
Action:dword;
FileNameLength:dword;
FileName:WideChar;
end;
var hDir,cbReturn:dword;
lpBuf:pointer;
Ptr:PFileNotifyInformation;
begin
//Path:='D:\Накладные';
hDir:=CreateFile(Path,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
while not Terminated do
begin
ZeroMemory(lpBuf,BUF_SIZE);
if(not ReadDirectoryChangesW(hDir,lpBuf,BUF_SIZE,true,FILE_NOTIFY_CHANGE_FILE_NAME
or FILE_NOTIFY_CHANGE_LAST_WRITE,@cbReturn,nil,nil))or(cbReturn=0)then Break;
// пользователь не сможет прервать ожидание, если захочет. Это нужно либо вынести в отдельный
// поток, либо использовать синхронный ввод/вывод
Ptr:=lpBuf;OldName:='';
// repeat
while not Terminated do
begin
GetMem(FileName,Ptr^.FileNameLength+2);
ZeroMemory(FileName,Ptr^.FileNameLength+2);
lstrcpynW(FileName,addr(Ptr^.FileName),Ptr.FileNameLength div 2+1);
case Ptr.Action of
FILE_ACTION_ADDED:Synchronize(UpdateLog);
end;
FreeMem(FileName);
if Ptr^.NextEntryOffset=0 then break;
Inc(integer(Ptr),Ptr^.NextEntryOffset);
// until false;
//until false;
end;
end;
FreeMem(lpBuf); // этот код ни разу не вызывается - программа останется в цикле до первой ошибки
CloseHandle(hDir);
end;
После выполнения FILE_ACTION_ADDED:Synchronize(UpdateLog);
не возвращается в цикл. Почему однако ???
petvv (2009-03-17 10:16:00) [21]Вот:
constructor TMonDirThread.Create(aPath: String);
begin
inherited Create(True);
FreeOnTerminate := True;
FPath := aPath;
Self.Priority := tpHighest;
Resume;
end;
procedure TMonDirThread.UpdateLog;
begin
Synchronize(TxtToDbf);
end;
procedure TMonDirThread.Execute;
Type PFileNotifyInformation=^TFileNotifyInformation;
TFileNotifyInformation=packed record
NextEntryOffset:dword;
Action:dword;
FileNameLength:dword;
FileName:WideChar;
end;
var hDir,cbReturn:dword;
lpBuf:pointer;
Ptr:PFileNotifyInformation;
begin
//Path:='D:\Накладные';
hDir:=CreateFile(Path,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
while not Terminated do
begin
ZeroMemory(lpBuf,BUF_SIZE);
if(not ReadDirectoryChangesW(hDir,lpBuf,BUF_SIZE,true,FILE_NOTIFY_CHANGE_FILE_NAME
or FILE_NOTIFY_CHANGE_LAST_WRITE,@cbReturn,nil,nil))or(cbReturn=0)then Break;
// пользователь не сможет прервать ожидание, если захочет. Это нужно либо вынести в отдельный
// поток, либо использовать синхронный ввод/вывод
Ptr:=lpBuf;OldName:='';
// repeat
while not Terminated do
begin
GetMem(FileName,Ptr^.FileNameLength+2);
ZeroMemory(FileName,Ptr^.FileNameLength+2);
lstrcpynW(FileName,addr(Ptr^.FileName),Ptr.FileNameLength div 2+1);
case Ptr.Action of
FILE_ACTION_ADDED:Synchronize(UpdateLog);
end;
FreeMem(FileName);
if Ptr^.NextEntryOffset=0 then break;
Inc(integer(Ptr),Ptr^.NextEntryOffset);
// until false;
//until false;
end;
end;
FreeMem(lpBuf); // этот код ни разу не вызывается - программа останется в цикле до первой ошибки
CloseHandle(hDir);
end;
Anatoly Podgoretsky (2009-03-17 10:10:00) [22]> petvv (17.03.2009 9:21:04) [4]
Тебе же сказано, что обращение к VCL должно идти через Synchronize, а ты не приводишь измененого кода. Пока это не сделаешь - говорить о другом нет смысла.
petvv (2009-03-17 10:05:00) [23]Направьте на путь истинный
petvv (2009-03-17 09:21:00) [24]Сделал следующее:
procedure TMonDirThread.UpdateLog;
begin
Synchronize(TxtToDbf);
end;
а в
procedure TMonDirThread.Execute;
...
case Ptr.Action of
FILE_ACTION_ADDED:Synchronize(UpdateLog);
end;
end;
Результат тотже :(
Или я чего не так делаю (понимаю) ?
petvv (2009-03-17 09:10:00) [25]т.е. не
CreateDBF();
а
Synchonize(CreateDBF);
и т.д.
Anatoly Podgoretsky (2009-03-17 09:04:00) [26]> petvv (17.03.2009 7:52:00) [0]
Обращение к VCL должно проходить через метод Synchonize
petvv (2009-03-17 08:01:00) [27]Т.е. получается, что это одноразовая операция и на следующие поступающие файлы уже не реагирует :(