Interrupting copy of large files

Nov 11, 2011 at 9:16 AM

Hi guys,

First post, so firstly thank you for a great library - I have just started with C# .Net and mobile development, and this has really made my life easier!

I have encountered (and been able to resolve) the following problem. I have only been working with C# for a month I will show you what I have done and leave up to you what would be the best/most correct way to implement it into the project (if you so wish of course).

 

Overview: I have a desktop application that allows a user to copy files to a device. I run the actual copy process in a BackbgroundWorker.

The scenario: Sometimes the files to be copied may be large, and as such I would like to allow the user the option to cancel the copy. Sending a CancelAsync() to the BackbgroundWorker will tell the worker thread that it should stop running at a safe point, but for this to happen the current file copy must first complete.

The problem: There is no way to interrupt the file copy

The solution: Add an InterruptCopy flag to the rapi class which will allow one to break out of the file copy process. Code below (my additions in red, ellipses denote exclusion of existing code for ease of reading):

 

 

namespace OpenNETCF.Desktop.Communication {
    public class RAPI : IRAPI {
	...

private bool m_blnInterruptCopy = false;
        public bool InterruptCopy {
            get {
                return m_blnInterruptCopy;
            }
            set {
                m_blnInterruptCopy = value;
            }
        }

		
        public void CopyFileToDevice(string LocalFileName, string RemoteFileName, bool Overwrite) {
	    ...

            // read 4k of data
            bytesread = localFile.Read(buffer, filepos, buffer.Length);
            m_blnInterruptCopy = false;
            while (bytesread > 0) {
                // Check if we must interrupt the copy process
                if (m_blnInterruptCopy) {
                    break;
                }
				
                // move remote file pointer # of bytes read
                filepos += bytesread;

                // write our buffer to the remote file
                if (!Convert.ToBoolean(CeWriteFile(remoteFile, buffer, bytesread, ref byteswritten, 0))) { // check for success
                    CeCloseHandle(remoteFile);
                    throw new RAPIException("Could not write to remote file");
                }
                try {
                    // refill the local buffer
                    bytesread = localFile.Read(buffer, 0, buffer.Length);
                }
                catch (Exception) {
                    bytesread = 0;
                }
	    }
			
            // close the local file
            localFile.Close();

            // close the remote file
            CeCloseHandle(remoteFile);

            // If the copy was interrupted then remove the incomplete file
            if (m_blnInterruptCopy) {
                DeleteDeviceFile(RemoteFileName);
            } else {
                // sync the date/times
                SetDeviceFileTime(RemoteFileName, RAPIFileTime.CreateTime, File.GetCreationTime(LocalFileName));
                SetDeviceFileTime(RemoteFileName, RAPIFileTime.LastAccessTime, DateTime.Now);
                SetDeviceFileTime(RemoteFileName, RAPIFileTime.LastModifiedTime, File.GetLastWriteTime(LocalFileName));
            }
        }

 

 

Then when I want to interrupt the copy of a large file in my code, I simply set the InterruptCopy flag to true:

 

m_rapi.InterruptCopy = true;

 

 

Obviously this can be extended to other file actions.

I hope this is a useful addition, I know that I searched for a solution for about 4 hours before I decided to brave trying it myself :)

Regards, 
Patric