views:

565

answers:

8

Hey Folks,

I've got a file organizer application I'm working on. The files are regularly 500MB to 2GB. Everything works fine, but it is extremely annoying that the application "Stops Responding." What I'd like to do is a byte by byte or meg by meg copy with some Application.DoEvents() in there after each read/write action. Something along these lines, I don't know what the actual classes to use would be so I'm just going to make some stuff up :)

private void CopyFile(string inFilename, string outFilename)
{
    FileReader inReader(inFilename);
    FileWriter outWriter(outFilename, FileMode.OpenOrCreate);

    byte theByte;
    while (theByte = inReader.ReadByte())
    {
        outWriter.WriteByte(theByte, WriteMode.Append);
        UpdateProgressBar();
        Application.DoEvents();
    }

    inReader.CloseFile();
    outWriter.CloseFile();
}

I know this seems like it should be a simple thing to do but I for the life of me can't seem to find any kind of example for doing this without using direct API calls or whatever. I've got to be missing something here so if anyone could get me on the right track here I'd really appreciate it.

Thanks in advance!

A: 

What you really want to do is have a multi-threaded application and do the file copy in a background thread, that way your main thread will not be tied up.

JonnyBoats
+4  A: 

You should use a BackgroundWorker on your form to do the copying. It will allow the file copies to be done on a separate thread and let your UI be responsive. There is some added complexity, but the BackgroundWorker takes care of a lot of the plumbing for you. But, there are plenty of examples of what you want to do.

JP Alioto
+1  A: 

Threading.ThreadPool.QueueUserWorkitem should get you well on your way.

hypoxide
+2  A: 

You need to use a BackgroundWorkerThread to accomplish this. Here's a very good example of how to do that: Copy File Using Background Worker Threads

Jose Basilio
+1  A: 

One approach is to perform the copy operation in a separate thread. Your main application will continue to run normally while the thread performs the work of copying the file. You'll of course want to add communication between the thread and the main application so you can update your progress bar or similar feedback mechanism.

If you'd rather not deal with multiple threads, another approach is to create a class that contains state variables for the copy operation and a member function that's called periodically from your main application in order to copy a certain number of bytes each time it's called.

Adrian Lopez
+2  A: 

I'd want to use the CopyFileEx function. If an analog to that function doesn't exist in the managed framework library, then Google for how to use it anyway: maybe an article like http://www.thetechscene.com/2008/09/copyfileex-with-progress-callback-in-c-using-pinvoke/

My reason for wanting to use CopyFileEx is that I assume it's implemented in the O/S kernel, with the data being copy from one file to another within the file system driver, without using user memory (let alone managed memory).

ChrisW
+1  A: 
Kyle Gagnet
+1  A: 

In addition to running a background thread, you should note that you're copying 512M-2G of data one byte at a time. This will translate into up to 2 BILLION calls to ReadByte and WriteByte. Hopefully those calls buffer somewhere so you don't make 2 BILLION managed to unmanaged transitions, but even so that will surely add up.

Memory isn't free, but it's sure as heck is cheap. Allocate a buffer (maybe 16K-64K) and copy in chunks. No, the code isn't as simple as you will need to handle one case of not reading the entire block, but I'd rather to 2G/64K method invocations over 2G.

plinth