Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a way to get my delphi program to wait for a large number of files to be copied?

Tags:

delphi

I have written a program that does the following...

  • Monitors a folder for the creation of a new file with a specific filename that will eventually be created in a sub folder.
  • On creation of the file, the sub folders path is added to a queue in the form of a TList.
  • The files must be processed in the creation order.
  • A procedure is called to process all the files (images in this case) in the subfolder which involves moving the files to a network location.
  • The subfolder path is removed from the queue (TList).
  • If any more paths exist in the queue, the next path is passed to the processing procedure.

The problem I am having is that the time to copy the files to a network location varies depending on the number and size of the images so...

Is there a way to get Delphi to wait for procedure of file operation to finish?

I tried a while loop that waited for a boolean value to change (changed when the last file to be copied was found on the network) but that hung the application (even with application.processMessage) and the dirMonitor component failed to add the next sub folder to the TList.

Any suggestions would be most appreciated.

Thanks in advance.


Thanks for the replys...

I had a look at OmniThread which looks ideal... although I only have access to Delphi 7 so its a no go.

The problem Im having is that the folders take varying amounts of time to transfer due to differing sizes and network traffic etc... When a folder with a lot of images is followed by a folder with only a few images, the smaller of the two is reaching the network destination first. The network desination being a third party print spooler so the prints come off in the wrong order.

The simplified code:

procedure TForm1.programTimerTimer(Sender: TObject);
begin
  if (fileOperationInProgress = false) AND (programPaused = false) then
    begin
      processOrderQueue;
    end;
end;

procedure TForm1.processOrderQueue;
begin
  // gets folder paths from queue
  // processes images
  // copy to print spooler (network location)

  copyFolder(fromPath, toPath);

  // remove temp files
end;

procedure TForm1.copyFolder(copyFrom : String; copyTo : String);
var
  fos : TSHFileOpStruct;
begin
  fileOperationInProgress := True;

  ZeroMemory(@fos, SizeOf(fos));

  with fos do
    begin
      wFunc  := FO_COPY;
      fFlags := FOF_FILESONLY or FOF_SILENT;
      pFrom  := PChar(copyFrom);
      pTo    := PChar(copyTo)
    end;

  ShFileOperation(fos);


  fileOperationInProgress := False;
end;

Think I've come up with the answer... I'm going to do all file operationions in a single thread and set a global 'busy' boolean when it starts and change it again on completion. That way the shell monitor won't miss messages when any file operations are in progress.

like image 358
Gavin Avatar asked Nov 21 '11 17:11

Gavin


1 Answers

You could implement a file system watch. Essentially, you create a file handle with the following flags:

CreateFile(PChar(FDirectoryToWatch), FILE_LIST_DIRECTORY or GENERIC_READ, 
FILE_SHARE_READ  or FILE_SHARE_WRITE or FILE_SHARE_DELETE, nil, OPEN_EXISTING, 
FILE_FLAG_BACKUP_SEMANTICS or FILE_FLAG_OVERLAPPED, 0);

and then create a loop to call ReadDirectoryChangesW.

Linked is an example class: Why does ReadDirectoryChangesW omit events?

The only thing I would do differently is provide an event in the creation of the class to notify of changes (remembering that when calling the event in the Execute procedure it probably needs to be Synchronized).

like image 138
tmjac2 Avatar answered Oct 06 '22 01:10

tmjac2