Reputation: 1
First of all sorry for this beginner question.
I am using net Framework 4.5 and can not go higher [this is probably important]
Trying to change my file copy code from
private Void to private async void
Why? - Because as long as the copy loop runs the whole process locks up
I have read a bit into async and await but it still seems a bit mistifying for me.
Can anyone please help me?
This is the code in question:
private async void CopyFilesRecursively(DirectoryInfo source, DirectoryInfo target)
{
if (target.GetFiles().Length > 0)
{
DeleteFilesRecursively(target);
CopyFilesRecursively(source, target);
}
else
{
foreach (DirectoryInfo dir in source.GetDirectories())
{
CopyFilesRecursively(dir, target.CreateSubdirectory(dir.Name));
}
foreach (FileInfo file in source.GetFiles())
{
progressPercentage = ++targetLength / (double)sourceLength;
Console.WriteLine(Convert.ToInt32(progressPercentage * 100).ToString() + "%");
PB_MW_FileTransfer.Value = Convert.ToInt32(progressPercentage * 100);
file.CopyTo(Path.Combine(target.FullName, file.Name), true);
}
}
}
I know I need to use await statement but no matter what I try it just gives me errors.
I tried background worker before but that is something I understand even less.
Please help me I am struggling so much with this.
just want to remind that Net Framework 4.5 is the one I use for various reasons [because of licensing]
Upvotes: 0
Views: 219
Reputation: 456322
Why? - Because as long as the copy loop runs the whole process locks up
Your goal is to free up the UI thread.
I tried background worker before but that is something I understand even less.
BackgroundWorker
is quite dated at this point. Your modern options are:
async
and await
, calling asynchronous BCL I/O methods. Ideally, this would be the best solution; however, in this case (asynchronous file I/O), the BCL support is less than ideal.Task.Run
, which is a modern replacement for BackgroundWorker
. Note that you would not want to use this option on ASP.NET or other server environment.Since you are on WinForms, Task.Run
would be a perfect fit:
private void CopyFilesRecursively(DirectoryInfo source, DirectoryInfo target) { ... }
// invoked as:
await Task.Run(() => CopyFilesRecursively(source, target));
Upvotes: 1
Reputation: 1
Hey there it is me again, if anyone else has a similar problem in the future.
This is what I changed my code into. Here to share it took me quite a while and a friend helped me on a couple of occasions [like how to create sub folders etc]
private async Task FolderCopyAsync(string source, string target)
{
foreach (string filename in Directory.EnumerateFiles(source, "*", SearchOption.AllDirectories))
{
using (FileStream SourceStream = File.Open(filename, FileMode.Open))
{
var targetFilename = target + filename.Substring(source.Length);
Directory.CreateDirectory(Path.GetDirectoryName(targetFilename));
using (FileStream DestinationStream = File.Create(targetFilename))
{
await SourceStream.CopyToAsync(DestinationStream);
}
}
}
}
Upvotes: 0
Reputation: 67362
Well for one thing you have to make your function return Task
, because you're going to want to await
it when you call it recursively. Plus every async
function in general should be a Task
, because presumably the point is that the caller needs to be able to await
it.
As mentioned in the comments, just making a function async
doesn't do anything by itself, you need to actually await
other async
functions for it to do anything. In particular for your case, you want to copy using FileStream.CopyToAsync
-- ie, open the source stream in read mode, open the destination stream in write mode and await
the copy method.
One point to notice is that async
file I/O is .Net Core 3, you won't find it in .Net Framework. If you persist with using it, either don't use async
at all, because the framework is not really built for it, or implement your own async
file I/O with the provided IAsyncResult
functions and TaskCompletionSource
to signal the TPL when copying is done.
Upvotes: 1