Page 1 of 1

Copying big file but quitting app during the copy

Posted: Fri Jul 15, 2016 1:08 am
by Dude
I wanted to know what happens if I purposely quit my app while it's copying a big file, and it seems the file is still copied in the background until complete. That is, I started the following code, ran it, killed it immediately, and when I checked the target folder the entire file showed up there after a minute.

So I have two questions:

(1) Is this normal behaviour and can be relied upon? Or is it OS-dependent, etc?

(2) Is there a way my app can know when the transfer is done, such as a progress check?

Thank you.

Code: Select all

CopyFile("S:\Source-1GB-Video.vob","T:\Target-1GB-Video.vob")

Re: Copying big file but quitting app during the copy

Posted: Fri Jul 15, 2016 2:03 am
by Keya
which OS are you using?? I'll assume Windows, in which case PB's CopyFile() uses kernel32's CopyFileA/W API function of the same name. That API won't return control to your app until it has finished ("blocking" i think thats called?), so your app and its GUI effectively hang while that's taking place if it's not done in another thread (so i guess if you click the Close button the window might hide but process will remain alive until the copy completes). Actually, id assume this blocking nature would be the case also with Linux and OSX, makes sense i guess? but i dont know if closing the Linux/OSX window would have the effect of terminating the primary thread immediately.

I don't know which file copy API functions support progress callbacks, but one option is to just manually copy it yourself with Repeat: ReadData(hCopyFromFile,(4096?)) -> WriteData(hCopyToFile): Until EOF(hCopyFromFile). Or if you're doing the CopyFile in another thread you can simply terminate the thread in which case yes it will stop immediately.
Somebody else will have a better answer though!

Re: Copying big file but quitting app during the copy

Posted: Fri Jul 15, 2016 2:27 am
by Dude
Keya wrote:which OS are you using?
Windows (note the "S:\" in the snippet). ;)

I think copying manually in chunks would be a lot slower than using CopyFile()?

Re: Copying big file but quitting app during the copy

Posted: Fri Jul 15, 2016 2:39 am
by Keya
Dude wrote:
Keya wrote:which OS are you using?
Windows (note the "S:\" in the snippet). ;)
forgive me ive still got a bit of Mondayitis. should be over it by Sunday night
Dude wrote:I think copying manually in chunks would be a lot slower than using CopyFile()?
i dunno, but that's ultimately how all file copy functions work!?! FWIW CopyFile calls CopyFileEx, and i just noticed on MSDN that yes, CopyFileEx DOES have a progress callback so i guess that's probably the way to go :)
Google suggests only 3 uses of it in Purebasic so far so you might have to be a bit of a trendsetter, but it looks like some working examples :)
http://www.google.com/search?q=%22CopyF ... 8&oe=utf-8

Re: Copying big file but quitting app during the copy

Posted: Fri Jul 15, 2016 4:23 am
by Dude
Keya wrote:but that's ultimately how all file copy functions work!?!
Yes, but myself doing it would be slower than the Windows API doing it. :)

Re: Copying big file but quitting app during the copy

Posted: Fri Jul 15, 2016 4:27 am
by Keya
but would it? :) i wonder because surely the disk i/o is the main bottleneck, so it may be equally fast using Read/WriteData? ... anyway just use CopyFileEx, lol :)

Re: Copying big file but quitting app during the copy

Posted: Sat Jul 16, 2016 6:34 am
by Dude
Okay, after checking out the links, I found and cleaned up some code from "Peter" (a moderator in a different forum).

Here's what I came up with, which works perfectly for my needs. Hope someone else can make use of it! :)

Code: Select all

#CopyFileWithProgressGadget=2000

#PROGRESS_CONTINUE=0
#PROGRESS_CANCEL=1

Global CopyFileWithProgressState
Global CopyFileWithProgressSource$
Global CopyFileWithProgressTarget$

Procedure.l CopyFileProgressCallback(TotalFileSize.q,TotalBytesTransferred.q,StreamSize.q,StreamBytesTransferred.q,dwStreamNumber.l,dwCallbackReason.l,hSourceFile.l,hDestinationFile.l,lpData.l)
  SetGadgetState(#CopyFileWithProgressGadget,(TotalBytesTransferred*100)/TotalFileSize)
  ProcedureReturn CopyFileWithProgressState
EndProcedure

Procedure CopyFileWithProgress_Thread(null)
  CopyFileWithProgressState=#PROGRESS_CONTINUE
  CopyFileEx_(@CopyFileWithProgressSource$,@CopyFileWithProgressTarget$,@CopyFileProgressCallback(),0,Flag,0)
  SetGadgetState(#CopyFileWithProgressGadget,0) ; Clear ProgressBarGadget when copy is done, to avoid confusion.
EndProcedure

If OpenWindow(0,100,100,120,100,"Copy")

  ProgressBarGadget(#CopyFileWithProgressGadget,10,10,100,20,1,100)
  ButtonGadget(1,10,40,100,20,"Copy")
  ButtonGadget(2,10,65,100,20,"Cancel")

  Repeat

    Event=WaitWindowEvent()

    If Event=#PB_Event_Gadget
      Select EventGadget()
        Case 1
          CopyFileWithProgressSource$="S:\1-GB-Video.vob"
          CopyFileWithProgressTarget$="T:\"+GetFilePart(CopyFileWithProgressSource$)
          CreateThread(@CopyFileWithProgress_Thread(),0) ; This starts the copy.
        Case 2
          CopyFileWithProgressState=#PROGRESS_CANCEL ; This cancels the copy.
      EndSelect
    EndIf

  Until Event=#PB_Event_CloseWindow

EndIf