5
\$\begingroup\$

Here is my effort to implement extensions for FileInfo object:

public static class FileExtensions
{
    public static async Task MoveFileAsync(this FileInfo file, string destinationPath, string destinationFileName = "")
    {
        await CopyFileAsync(file, destinationPath, destinationFileName).ContinueWith((x) =>
        {
            DeleteFileAsync(file);
        }, TaskContinuationOptions.OnlyOnRanToCompletion);
    }

    public static async Task CopyFileAsync(this FileInfo file, string destinationPath, string destinationFileName = "")
    {
        if (string.IsNullOrWhiteSpace(destinationFileName))
        {
            destinationFileName = file.Name;
        }

        using (FileStream SourceStream = file.Open(FileMode.Open))
        {
            using (FileStream DestinationStream = File.Create(Path.Combine(destinationPath, destinationFileName)))
            {
                await SourceStream.CopyToAsync(DestinationStream);
            }
        }
    }

    public static Task DeleteFileAsync(this FileInfo file)
    {
        return Task.Run(() =>
        {
            if (File.Exists(file.FullName))
            {
                File.Delete(file.FullName);
            }
        });
    }
}

The idea was to make it efficient, and basically, allow deleting in the background.

It feels like I mix things, but not sure what exactly is wrong.

So, I have a couple of questions for the beginning:

  1. The implementation of MoveFileAsync:

    • Is this the right way to implement it? I wanted to call the CopyFileAsync and when it is completed -> call DeleteFileAsync.
    • Do I need to add return before DeleteFileAsync(file);? (So that the method will return a task).
  2. The next step is using this DeleteFileAsync method within a loop. Like this:

public Task EmptyWorkingFolder()
{
    var directory = new DirectoryInfo(/*my-directory-path*/);
    var deleteTasks = new List<Task>();

    foreach (FileInfo file in directory.EnumerateFiles())
    {
        deleteTasks.Add(file.DeleteFileAsync());
    }

    return Task.WhenAll(deleteTasks);
}

Now my question is, how useful is this in comparison to just deleting the files synchronously?

Thanks for your time!

\$\endgroup\$
4
  • 1
    \$\begingroup\$ Few tips: 1) if (File.Exists(file.FullName)) a redundant check, look into File.Delete documentation. 2) there's no sense to make disk operations concurrent because file system anyway does all the jobs sequentially for single drive. Run one Task for all the Delete operations if you need to await it. Measure and compare the performance of the different implementations to be sure. 3) don't mix continuations with async/await approach. 4) names for the local variables must begin with lower-cased letter. \$\endgroup\$
    – aepot
    Dec 28 '21 at 23:21
  • \$\begingroup\$ Thanks for the tips @aepot. Could you please explain more about number 3? \$\endgroup\$
    – SeReGa
    Dec 29 '21 at 18:45
  • 2
    \$\begingroup\$ For example this await CopyFileAsync(file, destinationPath, destinationFileName).ContinueWith((x) => { DeleteFileAsync(file); }, TaskContinuationOptions.OnlyOnRanToCompletion); can be this await CopyFileAsync(file, destinationPath, destinationFileName); DeleteFileAsync(file); with exactly the same behavior. Continuations and async/await provides the same features but simply looks differently. Mixed code is harder to read. \$\endgroup\$
    – aepot
    Dec 29 '21 at 22:13
  • \$\begingroup\$ @aepot, now I see how it mixed, and I understand the example, however, how I will have to use 2 awaits in a row (for copy and for delete). So I think that it's better to use Task.WhenAll() to prevent losing errors. \$\endgroup\$
    – SeReGa
    Dec 30 '21 at 5:42

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.