Clarification regarding FolderItem.CopyTo

hi all, I’m using the FolderItem.Copy to command inside a Thread belonging to a window. In practice, this thread has to copy files in the background. Everything works, but when the file is large, the application freezes anyway and is unlocked when the copy is complete. Being inside a thread I would expect a different behavior.

can anyone explain to me what happens and how to solve it if necessary?

I have already decreased the priority of the thread that copies the files.

I operate on windows 10, xojo 2019 3.1 operating system

I’m speculating that you’re seeing this because threads are cooperative, not preemptive, and that function is blocking.

Solution 1: use an asynchronous Shell to copy the file. It won’t even have to be in a thread.

Solution 2: write your own copy function that copies the file in chunks in a loop and call that from a thread.

1 Like

thanks for your answer

I’m speculating that you’re seeing this because threads are cooperative, not preemptive, and that function is blocking.

I should go and review these 2 definitions, I honestly do not remember them at the moment

Solution 1: use an asynchronous Shell to copy the file. It won’t even have to be in a thread.

I had already thought about this solution, but when I finish copying I have to update a record of a database. and in my for the copy of several files is generated. I should therefore N shell as many as there are files. or manage the files one at a time. Other problems arise

Solution 2: write your own copy function that copies the file in chunks in a loop and call that from a thread.

this i don’t know at all how to implement it. Anyway I saw that the problem also exists with different files

Unfortunately, Xojo file IO commands block all threads. I logged case 52196 to add support for non blocking IO.

Solutions…
1.If you have the MBS plugins you could use WindowsFileCopyMBS as that doesn’t block when called within a Xojo thread (NSFileManagerMBS can be used on macOS).

2.Perform the copy via an async shell.

3.Copy the file in blocks.

4.Use a Xojo worker.

It is also worth noting that this is the kind of problem that would be easy to solve if Xojo threads could be pre-emptive rather than cooperative.

I also thank you for the reply. I’ll try with MBS plugins (WindowsFileCopyMBS).

Eventually I will try to come up with something with asynchronous shell calls, but I hope there is no need.

Thanks again

Some pointers for WindowsFileCopyMBS…

1.It will still block when called from the main thread.
2.You need to set the MultiThreaded flag on the class instance.

Here is some rough code i’ve quickly pulled from a project to get you started:

NOTE. pSource & pDestination are both FolderItems.

Const kCOPY_FILE_NO_BUFFERING = &h1000

Dim destFolderItem As FolderItem
Dim copyObj As WindowsFileCopyMBS
Dim copyResult As Boolean

If pDestination.Directory = True Then
   destFolderItem = pDestination.Child(pSource.Name)
Else
   destFolderItem = pDestination
End If
        
copyObj = New WindowsFileCopyMBS
copyObj.MultiThreaded = True
        
'first try with no buffering
copyResult = copyObj.CopyFileEx(pSource, destFolderItem, kCOPY_FILE_NO_BUFFERING)
        
'if we have an error and it is due to the parameter not being supported on the operating system perform a normal copy
If (copyResult = False) And (copyObj.LastError = 87) Then
   copyResult = copyObj.CopyFileEx(pSource, destFolderItem, 0)
End If

I will try. I’ll study the examples of the plugins also (“Windows File Copy” e “Windows File Copy Threaded”).

You get an event Completed when the task is complete.
https://documentation.xojo.com/api/os/shell.html

  1. Add a Generic Object to the window
  2. In the inspector for the Generic Object, click the pencil and scroll down to select Shell
  3. Select asynchronous
  4. Add an event handler for the Completed event.

You can then use Object1 (or whatever name you chose for the shell) like

Object1.execute("cp my.txt my1.txt")

The Completed event will fire when copy is complete.

Thank you for your suggestion. I’ve used the Shell class before, albeit mostly in synchronous mode. At that point, having several files to delete, I should just create a queue “manager” (a copy might fail, but I would still like to copy all the other files … I should solve with a try / catch inside a for).
Thanks again