2012-03-30 14 views
6

Si lo ejecuto de esa manera mi aplicación no responderá hasta encontrar todos los archivos en el listbox mi pregunta es ¿Cómo puedo hacer que esta función se multiplique para evitar situaciones que no correspondan? todavía estoy Delphi novoicebúsqueda de archivos delphi multiprocesamiento

procedure TfrMain.FileSearch(const PathName, FileName : string; txtToSearch : string; const InDir : boolean); 
var Rec : TSearchRec; 
    Path : string; 
    txt : string; 
    fh : TextFile; 
    i : integer; 
begin 


Path := IncludeTrailingBackslash(PathName); 
if FindFirst(Path + FileName, faAnyFile - faDirectory, Rec) = 0 then 
try 
    repeat 

    AssignFile(fh, Path + Rec.Name); 
    Reset(fh); 
    Readln(fh,txt); 

    if ContainsStr(txt, txtToSearch) then 
     ListBox1.Items.Add(Path + Rec.Name); 

    until FindNext(Rec) <> 0; 
finally 
    FindClose(Rec); 

end; 

If not InDir then Exit; 

if FindFirst(Path + '*.*', faDirectory, Rec) = 0 then 
try 
    repeat 
    if ((Rec.Attr and faDirectory) <> 0) and (Rec.Name<>'.') and (Rec.Name<>'..') then 
    FileSearch(Path + Rec.Name, FileName, txtToSearch, True); 
    until FindNext(Rec) <> 0; 
finally 
    FindClose(Rec); 
end; 
end; 

Respuesta

5

Se puede retener la materia de análisis de archivos en un hilo y whenver trabajo está terminado enviar un mensaje de ventanas para el formulario principal, que a su vez actualiza el cuadro de lista (código no probado, tomarlo como pseudo-código):

const 
    WM_FILESEARCH_FINISHED = WM_USER + 1; 

TFileSearchThread = class (TThread) 
private 
    FPath  : String; 
    FFileNames : TStringList; 
protected 
    procedure Execute; override; 
public 
    constructor Create (const Path : String); 
    destructor Destroy; override; 
    property FileNames : TStrings read FFileNames; 
end; 

constructor TFileSearchThread.Create (const Path : String); 
begin 
    inherited Create (True); 
    FPath := Path; 
    FFileNames := TStringList.Create; 
end; 

destructor TFileSearchThread.Destroy; 
begin 
    FreeAndNil (FFileNames); 
    inherited; 
end; 

procedure TFileSearchThread.Execute; 
begin 
    // do your file search here, adding each file to FFileNames 
    PostMessage (MainForm.Handle, WM_FILESEARCH_FINISHED, 0, 0); 
end; 

se puede utilizar de esta manera:

Thead := TFileSearchThread.Create (Path); 
Thread.Start; 

y la principal forma tendría un controlador de mensajes como éste:

type 
    TMainForm = class(TForm) 
    ListBox1: TListBox; 
    private 
    procedure WMFileSearchFinished (var Msg : TMessage); message WM_FILESEARCH_FINISHED; 
    public 
    { Public declarations } 
    end; 

implementation 

procedure TMainForm.WMFileSearchFinished (var Msg : TMessage); 
begin 
    ListBox1.Items.AddStrings (Thread.FileNames); 
end; 
+1

+1, solución simple y limpia. No hay mucho que pueda salir mal. –

+0

No debería el 'PostMessage (MainForm.Handle, WM_FILESEARCH_FINISHED, 0, 0); 'ser utilizado con' Sincronizar'? – kobik

+1

@kobik, no hay necesidad de preocuparse, la propiedad 'Handle' es de solo lectura y su lectura es atómica. Y tiene que ser diferente de 0 (el control estaría muerto y no podría recibir ningún mensaje), por lo que el getter nunca 'CreateHandle' hará lo mismo cuando el handle sea 0. El riesgo es la instancia del objeto en sí, si destruye 'MainForm' e intenta acceder a él, obtendrás AV como siempre. Y, Emba ['uses'] (http://edn.embarcadero.com/article/22411) esto también :-) – TLama

Cuestiones relacionadas