I am using the following method to copy the contents of a directory to a different directory.
public void DirCopy(string SourcePath, string DestinationPath)
{
if (Directory.Exists(DestinationPath))
{
System.IO.DirectoryInfo downloadedMessageInfo = new DirectoryInfo(DestinationPath);
foreach (FileInfo file in downloadedMessageInfo.GetFiles())
{
file.Delete();
}
foreach (DirectoryInfo dir in downloadedMessageInfo.GetDirectories())
{
dir.Delete(true);
}
}
//=================================================================================
string[] directories = System.IO.Directory.GetDirectories(SourcePath, "*.*", SearchOption.AllDirectories);
Parallel.ForEach(directories, dirPath =>
{
Directory.CreateDirectory(dirPath.Replace(SourcePath, DestinationPath));
});
string[] files = System.IO.Directory.GetFiles(SourcePath, "*.*", SearchOption.AllDirectories);
Parallel.ForEach(files, newPath =>
{
File.Copy(newPath, newPath.Replace(SourcePath, DestinationPath), true);
});
}
My only issue is that there is quite a bit of data in the source path and the program becomes non responsive while the copying is taking place.
I am wondering what my options are for copying data. I did some research and someone had recommended to use a buffer.
I have not really seen any solution that I understand particularly well so any help/resources that are clear and concise would be great.
Thanks for any help!
If your goal is to stop the application from going into a non-responsive state, the suggested method to use buffers will not fix your problem. Instead, look at using a seperate
Thread
to copy your directories.Even better, use a
BackgroundWorker
, which has the added benefit of being able to report progress.A quick fix for your issue is to use a background thread at the calling code like this:
This example uses the
Task.Run
method which uses one of the thread-pool threads to execute the code.This makes sure that the UI thread is free to update the UI and to respond to user input.
Performing long tasks in Windows Forms, on the message thread will cause the form to become unresponsive until the task is done. You're going to need to use threading to prevent that. It can get complicated, but you're going to need a BackgroundWorker:
A method that preforms the task:
And a method to report progress:
You can use a marquee progress bar, but if you want to report the actual percentage back, calculating file sizes and progress in your Worker_DoWork method can become complicated and is another issue.
https://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker(v=vs.110).aspx
Assuming that the real problem is your program becoming non-responsive...
Your program probably stops responding because the thread you're using to perform the copies is the thread you leverage to respond to user input. If you want copies to continue in the background while the program remains responsive, you must perform the copies asynchronously. (I assume that you're using winforms or wpf based on your context.)
The typical approach is to simply spin up a background worker, ship the copy job off to it, and let it go to town while your gui thread responds to user input. There are other more sophisticated techniques with better trade offs as well, but I suspect this will suffice for your scenario based on what you've described.
(Your
Parallel.ForEach
doesn't do the trick because the thread that triggers it will not continue until theParallel.ForEach
has finished executing)It's not clear what version of the compiler / framework you're using, but you could use asynchronous file operations and not have to worry about threading. You could also benefit from using the streaming versions
EnumerateDirectories
andEnumerateFiles
if you have large file hierarchies.Thanks everyone I really appreciate all the input to see the different ways to accomplish this. For the time being I decided to just do a Task.Run but I am going to look into the background worker and asynch operations.
Thanks again everyone!
For reference I just did
DirCopy