Non-blocking file copy in C#

Viewed 77769

How can I copy a file in C# without blocking a thread?

10 Answers

You can use asynchronous delegates

public class AsyncFileCopier
    {
        public delegate void FileCopyDelegate(string sourceFile, string destFile);

        public static void AsynFileCopy(string sourceFile, string destFile)
        {
            FileCopyDelegate del = new FileCopyDelegate(FileCopy);
            IAsyncResult result = del.BeginInvoke(sourceFile, destFile, CallBackAfterFileCopied, null);
        }

        public static void FileCopy(string sourceFile, string destFile)
        { 
            // Code to copy the file
        }

        public static void CallBackAfterFileCopied(IAsyncResult result)
        {
            // Code to be run after file copy is done
        }
    }

You can call it as:

AsyncFileCopier.AsynFileCopy("abc.txt", "xyz.txt");

This link tells you the different techniques of asyn coding

You can do it as this article suggested:

public static void CopyStreamToStream(
    Stream source, Stream destination,
    Action<Stream, Stream, Exception> completed)
    {
        byte[] buffer = new byte[0x1000];
        AsyncOperation asyncOp = AsyncOperationManager.CreateOperation(null);

        Action<Exception> done = e =>
        {
            if(completed != null) asyncOp.Post(delegate
                {
                    completed(source, destination, e);
                }, null);
        };

        AsyncCallback rc = null;
        rc = readResult =>
        {
            try
            {
                int read = source.EndRead(readResult);
                if(read > 0)
                {
                    destination.BeginWrite(buffer, 0, read, writeResult =>
                    {
                        try
                        {
                            destination.EndWrite(writeResult);
                            source.BeginRead(
                                buffer, 0, buffer.Length, rc, null);
                        }
                        catch(Exception exc) { done(exc); }
                    }, null);
                }
                else done(null);
            }
            catch(Exception exc) { done(exc); }
        };

        source.BeginRead(buffer, 0, buffer.Length, rc, null);

I implemented this solution for copying large files (backup files) and it's terribly slow! For smaller files, it's not a problem, but for large files just use File.Copy or an implementation of robocopy with parameter /mt (multithread).

Note that this, copy file async, is still an open issue for .net development: https://github.com/dotnet/runtime/issues/20695

The correct way to copy: use a separate thread.

Here's how you might be doing it (synchronously):

//.. [code]
doFileCopy();
// .. [more code]

Here's how to do it asynchronously:

// .. [code]
new System.Threading.Thread(doFileCopy).Start();
// .. [more code]

This is a very naive way to do things. Done well, the solution would include some event/delegate method to report the status of the file copy, and notify important events like failure, completion etc.

cheers, jrh

Related