2015-02-25 4 views
0

У меня есть 2 функции, которые могут сказать мне, если файл используется, проверяя, увеличивается ли размер файла. Для работы мне нужно использовать задержку в 5000 мс между каждым размером собранных из того же файла. Это нормально, но он блокирует мой основной поток, поэтому я должен поместить функции внутри потока. Вот функции, которые я использую. Как я могу создать поток, в котором я выполняю функции и получаю результат? Ниже перечислены функции, которые я использую в данный момент. Спасибо!Запустить функцию внутри потока и получить результат

function GetFileSize_mmg(const FileName: string): Int64; 
var 
    fad: TWin32FileAttributeData; 
begin 
    if not GetFileAttributesEx(PChar(FileName), GetFileExInfoStandard, @fad) then 
    RaiseLastOSError; 
    Int64Rec(Result).Lo := fad.nFileSizeLow; 
    Int64Rec(Result).Hi := fad.nFileSizeHigh; 
end; 


function does_size_changes(filename:string; delay:integer;memo_loguri:Tmemo): boolean; 
var size1,size2:int64; 
begin 
result:=false; 
size1:=GetFileSize_mmg(filename); 
sleep(delay); 
size2:= GetFileSize_mmg(filename); 

if size1 <> size2 then 
begin 
result:=true; 
memo_loguri.Lines.Add(datetimetostr(now)+' - file "'+filename+'" is growing: ' +inttostr(size1)+' < '+inttostr(size2)); 
end 

else 
begin 
result:=false; 
memo_loguri.Lines.Add(datetimetostr(now)+' - file "'+filename+'" can be used: '+ inttostr(size1)+' = '+inttostr(size2)); 
end; 
end; 
+0

Вместо того чтобы запрашивать размер файла с течением времени, почему бы просто не спросить ОС, если файл используется? Вы можете попробовать открыть файл в эксклюзивном режиме и посмотреть, произошла ли ошибка нарушения доступа. Или используйте интерфейс ['IFileIsInUse'] (https://msdn.microsoft.com/en-us/library/bb775874.aspx). –

+0

Я уже пробовал это. Работает нормально во всех тестируемых ОС, за исключением того, что файлы были экспортированы из стороннего программного обеспечения. Это специальная ОС, созданная для хранения кластера. Похоже, что в ОС сервера есть ошибка. Я уже говорил с администратором сервера и предупреждал его о большой проблеме безопасности в отношении блокировок файлов (я смог удалить файл, когда он записывался из другого приложения.) До тех пор, пока администратор не исправил эту проблему, я должен изменить свое приложение так что я могу проверить файлы перед их обработкой. – user2858981

ответ

-1

Мне удалось выполнить эту работу и синхронизировать gui с результатом. В одном списке я храню файлы, которые находятся в использовании, а в другом списке я храню файлы, которые могут быть обработаны. Следующая тема решает проблему с зависанием gui, и для обработки всех файлов требуется всего 5 секунд. Я загружаю все файлы в список (listbox_fisiere_in_uz). Я проверяю файлы, используя нижеследующий поток. Если файлы не растут по размеру, я перемещаю их во второй список (ListBox_fisiere_restore_vme).

function GetFileSize_mmg(const FileName: string): Int64; 
var 
    fad: TWin32FileAttributeData; 
begin 
    if not GetFileAttributesEx(PChar(FileName), GetFileExInfoStandard, @fad) then 
    RaiseLastOSError; 
    Int64Rec(Result).Lo := fad.nFileSizeLow; 
    Int64Rec(Result).Hi := fad.nFileSizeHigh; 
end; 

type 
    TThread_verificare_fisiere_in_uz = class(TThread) 
    private 
    Variabila_fisier: string; 
    variabila_interval_verificare:integer; 
    size1, size2: Int64; 
    raspuns_verificare_stare_fisier:string; 
    test_raspuns:string; 
    protected 
    procedure Execute; override; 
    procedure AfisareRezultat; 
    public 
    constructor Create(nume_fisier:string;interval:integer); 
    end; 



constructor TThread_verificare_fisiere_in_uz.Create; 
begin 
    inherited Create(false); 
    Variabila_fisier := nume_fisier; 
    variabila_interval_verificare:= interval; 
end; 

procedure TThread_verificare_fisiere_in_uz.Execute; 
begin 

    raspuns_verificare_stare_fisier := 'false'; 
    size1 := GetFileSize_mmg(Variabila_fisier); 
    sleep(variabila_interval_verificare); 
    size2 := GetFileSize_mmg(Variabila_fisier); 



    if size1 <> size2 then 
    begin 
    raspuns_verificare_stare_fisier := 'true'; 
    test_raspuns:='Fisierul '+Variabila_fisier+' este in curs de scriere:'+inttostr(size1)+'<>'+inttostr(size2); 
    Synchronize(AfisareRezultat); 
    end; 

    if size1 = size2 then 
    begin 
    raspuns_verificare_stare_fisier := 'false'; 
    test_raspuns:='Fisierul '+Variabila_fisier+' nu este in uz'+inttostr(size1)+'='+inttostr(size2); 
    Synchronize(AfisareRezultat); 
    end; 

end; 


procedure TThread_verificare_fisiere_in_uz.AfisareRezultat; 
var index_fisier_verificat:integer; 
    fisier_in_curs_de_verificare:string; 
    raspuns:string; 

begin 
{detectez index-ul fisierului in curs de verificare dupa numele fisierului pe care il verific} 
index_fisier_verificat:= form2.ListBox_fisiere_in_uz.Items.IndexOf(variabila_fisier); 
fisier_in_curs_de_verificare:= variabila_fisier; 
raspuns:= raspuns_verificare_stare_fisier; 

if raspuns_verificare_stare_fisier = 'true' then 
    begin 
    Form2.Memo_loguri.Lines.Add(datetimetostr(now) + 
     ' - dimensiunea fisierului "' + fisier_in_curs_de_verificare + '" creste: ' + inttostr 
     (size1) + ' < ' + inttostr(size2) + 
     ' => fisierul este in proces de scriere'); 

    end; 

    if raspuns_verificare_stare_fisier = 'false' then 
    begin 
    Form2.Memo_loguri.Lines.Add(datetimetostr(now) + 
     ' - dimensiunea fisierului "' + fisier_in_curs_de_verificare + '" nu se modifica: ' + 
     inttostr(size1) + ' = ' + inttostr(size2) 
     + ' => fisierul nu este in uz'); 
    begin 


if not exista_textul_in_listbox(Form2.ListBox_fisiere_in_uz.Items[index_fisier_verificat],Form2.ListBox_fisiere_restore_vme) then 
     Form2.ListBox_fisiere_restore_vme.Items.Add(Form2.ListBox_fisiere_in_uz.Items[index_fisier_verificat]); 


if Form2.ListBox_fisiere_in_uz.Items.count > 0 then Form2.ListBox_fisiere_in_uz.Items.Delete(index_fisier_verificat); 
    end 
    end; 

end; 
+0

'index_element_verificat: = i;' неверно в TThread_verificare_fisiere_in_uz.Create; Передайте значение в качестве параметра в конструкторе create. –

+0

Спасибо, LU RD, вы правы! Теперь он работает нормально. – user2858981

0

Некоторые опции:

  1. Stop с использованием потоков и заменить таймер с интервалом 5000 мс.
  2. Использовать общий объект событий для потоковой защиты.
  3. Использование общего логического. У этого будет гонка данных, но хорошая.
  4. Поместить сообщение в основном разделе как уведомление.
  5. Использовать TThread.Synchronize для синхронного уведомления.
+0

Не могли бы вы привести пример того, как сделать такой поток? – user2858981

+1

Почему вы не выбираете вариант 1 и не делаете его простым? –

+0

Потому что у меня уже есть таймер на основной форме, которая срабатывает каждые 50 секунд. – user2858981

 Смежные вопросы

  • Нет связанных вопросов^_^