I'm currently creating an application that allows me to select a directory and have it copied to upto 4 different location depending on what you've selected
And the moment when it copies the main for locks up so I want to get the directory copies running on different threads to stop this from happening. On top of that I need to link up the progress bars for each directory copy to show progress of the transfer.
I'm a bit rusty when it comes to c# and would love it if someone could point me in the right direction. I tried using await/async but it would still just run each directory copy after each other not at the same time.
private void button1_Click(object sender, EventArgs e)
{
//
// This event handler was created by double-clicking the window in the designer.
// It runs on the program's startup routine.
//
Path.GetFileName(folderBrowserDialog1.SelectedPath);
folderBrowserDialog1.RootFolder = Environment.SpecialFolder.MyComputer;
folderBrowserDialog1.SelectedPath = @"C:\Delivery";
DialogResult result = folderBrowserDialog1.ShowDialog();
if (result == DialogResult.OK)
{
//
// The user selected a folder and pressed the OK button.
// We print the number of files found.
//
// string[] files = Directory.GetFiles(folderBrowserDialog1.SelectedPath);
// MessageBox.Show("Files found: " + files.Length.ToString(), "Message");
if (checkBox1.Checked == true)
{
DirectoryCopy(folderBrowserDialog1.SelectedPath, "C:\\temp\\1\\" + Path.GetFileName(folderBrowserDialog1.SelectedPath), true);
}
if (checkBox2.Checked == true)
{
DirectoryCopy(folderBrowserDialog1.SelectedPath, "C:\\temp\\2\\" + Path.GetFileName(folderBrowserDialog1.SelectedPath), true);
}
if (checkBox3.Checked == true)
{
DirectoryCopy(folderBrowserDialog1.SelectedPath, "C:\\temp\\3\\" + Path.GetFileName(folderBrowserDialog1.SelectedPath), true);
}
if (checkBox4.Checked == true)
{
DirectoryCopy(folderBrowserDialog1.SelectedPath, "C:\\temp\\4\\" + Path.GetFileName(folderBrowserDialog1.SelectedPath), true);
}
if (checkBox5.Checked == true)
{
DirectoryCopy(folderBrowserDialog1.SelectedPath, "C:\\temp\\5\\"+ Path.GetFileName(folderBrowserDialog1.SelectedPath), true);
}
MessageBox.Show("These folders have been successfully transfered");
}
}
Your question has several issues:
How to copy the directories using async-await
Every function that uses async-await has to return
Task
instead ofvoid
andTask<TResult>
instead ofTResult
. There is one exception: the async event handler. The event handler returns void.MSDN about Asynchronous File I/O comes with the following:
Your directory copier would could be like this:
Finally your event handler:
Feedback in your UI
If it is enough to update your progress bar for every copied file, consider to let the FolderCopier raise an event whenever a file is copied.
Registering to these events:
Efficiency during file copy
You want to copy every source file to several locations. If you do this in separate processes, your source file will be read once per destination file. It seems much more efficient to read the source file once and write them to all destination files.
In all my examples, I use pure async-await without starting a new thread. Only one thread is involved (or to be more precise: only one thread at a time). How can this make your process faster?
In this interview Eric Lippert compared async await with a team of cooks who have to prepare dinner (search somewhere in the middle of the article for async-await).
In Eric Lippert's analogy, if a cook has to wait for the bread to toast, he won't be lazily doing nothing. Instead he looks around to see if he can do something else. After a while when the bread is toasted he continues processing the toasted bread, or in a team of cooks: one of his colleagues processes the toasted bread.
The same is in async-await. Your thread can only do one thing at a time, and as long as he is busy he can't do anything else. During the directory copy there are several times your thread would be waiting, namely during reading the source file and during writing the destination file. So if you tell your thread to do something else instead of waiting, it might speed up the process.
So at first glance it seems that async-await would help you: while waiting for the first file to be written, your thread could start reading your second file. Alas, the device that writes your file will probably be the same as the one that reads your files, and thus your device would be too busy to handle your request to read the second file. So I'm not sure if your process will be much faster if you use async-await.
The same is if you really start several threads. It will only be faster if the writing is to different devices.
If you only want to keep your UI responsive consider using a BackGroundWorker class. Easier to start and stop, and easier to report progress.