Listview and threaded filecopy

J

John Rogers

Can someone offer some advice.

I have the following code that works to do a threaded file copy.

private void CopyFolder(object o)
{
string sourceFolderPath = "Source Not Found";
string destinationFolderPath = "Destination Not Found";
bool overwrite = false;

try
{
sourceFolderPath = ((string)(((object[])o)[0]));
destinationFolderPath = ((string)(((object[])o)[1]));
overwrite = ((bool)(((object[])o)[2]));

if (Directory.Exists(sourceFolderPath))
{
if (Directory.Exists(destinationFolderPath + "\\" + (new
DirectoryInfo(sourceFolderPath).Name)) && (!overwrite))
throw new System.Exception("Sorry, but the folder "
+ destinationFolderPath + " already exists.");
else if (!Directory.Exists(destinationFolderPath + "\\"
+ (new DirectoryInfo(sourceFolderPath).Name)))
Directory.CreateDirectory(destinationFolderPath +
"\\" + (new DirectoryInfo(sourceFolderPath).Name));

//Copy all the files
FileInfo[] fiA = (new
DirectoryInfo(sourceFolderPath).GetFiles());
foreach (FileInfo fi in fiA)
{
//writeStatus("Copying " + fi.FullName + " to " +
destinationFolderPath + "\\" + (new DirectoryInfo(sourceFolderPath).Name) +
"\\");
writeStatus(fi.FullName);
fi.CopyTo(destinationFolderPath + "\\" + (new
DirectoryInfo(sourceFolderPath).Name) + "\\" + fi.Name);
}

//Recursively fill the child directories
DirectoryInfo[] diA = (new
DirectoryInfo(sourceFolderPath).GetDirectories());
foreach (DirectoryInfo di in diA)
{
writeStatus("Copying " + di.FullName + " to " +
destinationFolderPath + "\\" + (new DirectoryInfo(sourceFolderPath).Name) +
"\\");
CopyFolder(new object[] { di.FullName,
destinationFolderPath + "\\" + (new DirectoryInfo(sourceFolderPath).Name),
overwrite });
}
}
else
writeStatus("Sorry, source folder " + sourceFolderPath +
" doesn't exist.");
}
catch (System.Exception ex)
{
writeStatus("Sorry an error occurred while copying " +
sourceFolderPath + ": " + ex.Message);
}
}

private void btnCopy_Click(object sender, EventArgs e)
{
int FileCount = listView.Items.Count;
// Start the copy process
thread = new System.Threading.Thread(new
System.Threading.ParameterizedThreadStart(CopyFolder));
thread.Start(new object[] { tbSource.Text, tbDestination.Text,
true });
}

I want to add a listview to the code. I will add all of my directories to
the listview, then when I
click copy it will go through each entry into the listview and do the
copying.

My problem is I really don't know how to implement the listview into the
code. If I do something
like

int FileCount = listView.Items.Count;
if(FileCount > 0)
{
thread = new System.Threading.Thread(new
System.Threading.ParameterizedThreadStart(CopyFolder));
// read the source entry from the lisview and add it here to the
thread
thread.Start(new object[] { tbSource.Text, tbDestination.Text,
true });
}

I don't think this will work because it will create a ton of threads, which
I don't want.
What do I have to do to go through the listView, and select one item at a
time. Then when
it's finished copying that item, move to the other item and copy that, until
it copies everything.


Thanks

John-
 
N

Nicholas Paldino [.NET/C# MVP]

John,

You are just passing the currently selected item. What you need to do
is cycle through all the items before you create the new thread, and pass
all the sources and all the destinations (an array, or dictionary would be
good here) and then cycle through those in your worker thread.


--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)

John Rogers said:
Can someone offer some advice.

I have the following code that works to do a threaded file copy.

private void CopyFolder(object o)
{
string sourceFolderPath = "Source Not Found";
string destinationFolderPath = "Destination Not Found";
bool overwrite = false;

try
{
sourceFolderPath = ((string)(((object[])o)[0]));
destinationFolderPath = ((string)(((object[])o)[1]));
overwrite = ((bool)(((object[])o)[2]));

if (Directory.Exists(sourceFolderPath))
{
if (Directory.Exists(destinationFolderPath + "\\" +
(new DirectoryInfo(sourceFolderPath).Name)) && (!overwrite))
throw new System.Exception("Sorry, but the folder "
+ destinationFolderPath + " already exists.");
else if (!Directory.Exists(destinationFolderPath + "\\"
+ (new DirectoryInfo(sourceFolderPath).Name)))
Directory.CreateDirectory(destinationFolderPath +
"\\" + (new DirectoryInfo(sourceFolderPath).Name));

//Copy all the files
FileInfo[] fiA = (new
DirectoryInfo(sourceFolderPath).GetFiles());
foreach (FileInfo fi in fiA)
{
//writeStatus("Copying " + fi.FullName + " to " +
destinationFolderPath + "\\" + (new DirectoryInfo(sourceFolderPath).Name)
+ "\\");
writeStatus(fi.FullName);
fi.CopyTo(destinationFolderPath + "\\" + (new
DirectoryInfo(sourceFolderPath).Name) + "\\" + fi.Name);
}

//Recursively fill the child directories
DirectoryInfo[] diA = (new
DirectoryInfo(sourceFolderPath).GetDirectories());
foreach (DirectoryInfo di in diA)
{
writeStatus("Copying " + di.FullName + " to " +
destinationFolderPath + "\\" + (new DirectoryInfo(sourceFolderPath).Name)
+ "\\");
CopyFolder(new object[] { di.FullName,
destinationFolderPath + "\\" + (new DirectoryInfo(sourceFolderPath).Name),
overwrite });
}
}
else
writeStatus("Sorry, source folder " + sourceFolderPath
+ " doesn't exist.");
}
catch (System.Exception ex)
{
writeStatus("Sorry an error occurred while copying " +
sourceFolderPath + ": " + ex.Message);
}
}

private void btnCopy_Click(object sender, EventArgs e)
{
int FileCount = listView.Items.Count;
// Start the copy process
thread = new System.Threading.Thread(new
System.Threading.ParameterizedThreadStart(CopyFolder));
thread.Start(new object[] { tbSource.Text, tbDestination.Text,
true });
}

I want to add a listview to the code. I will add all of my directories to
the listview, then when I
click copy it will go through each entry into the listview and do the
copying.

My problem is I really don't know how to implement the listview into the
code. If I do something
like

int FileCount = listView.Items.Count;
if(FileCount > 0)
{
thread = new System.Threading.Thread(new
System.Threading.ParameterizedThreadStart(CopyFolder));
// read the source entry from the lisview and add it here to the
thread
thread.Start(new object[] { tbSource.Text, tbDestination.Text,
true });
}

I don't think this will work because it will create a ton of threads,
which I don't want.
What do I have to do to go through the listView, and select one item at a
time. Then when
it's finished copying that item, move to the other item and copy that,
until it copies everything.


Thanks

John-
 
J

John Rogers

Thats where I am lost, how do you know when the thread is finished
so you can pass it another entry to process. Can you provide me with
a small example?


Thanks

John-
 
N

Nicholas Paldino [.NET/C# MVP]

John,

That's the thing, why pass it another entry? Why not create the list of
files to copy, and then pass that list to a method on another thread? Then,
on the other thread, cycle through the list and perform the file copy.

So basically, create a method called CopyFolders which you pass a
Dictionary<string, string> (where the key is the source, and the value is
the destination) and then pass that as your thread routine.

Then, in CopyFolders, enumerate through the keys, and get the values,
calling CopyFolder (which you would change to take a source/destination
parameter) for each key/value pair.

Having multiple threads perform a file copy probably isn't going to give
you much of a performance boost, so one thread is appropriate here, as you
want to keep the UI active.
 
Top