异步文件和文件夹副本 - C#

时间:2013-12-19 18:48:13

标签: c# multithreading asynchronous file-io copy

我有一种方法可以将一个目录中的所有文件和文件夹复制到另一个目录中,并且它可以递归地工作。我的问题是它阻止了主线程,我想使文件和文件夹的实际复制异步。我目前正在使用一个函数来异步复制文件,但它似乎不起作用。 这是代码:

private async void copyEverything(string source, string target)
    {
        // Variable to hold the attributes of a file
        FileAttributes attributes;

        // Get the subdirectories for the specified directory.
        DirectoryInfo dir = new DirectoryInfo(source);
        DirectoryInfo[] dirs = dir.GetDirectories();

        if (!dir.Exists)
        {
            throw new DirectoryNotFoundException(
                "Source directory does not exist or could not be found: " + source);
        }

        // If the destination directory doesn't exist, create it. 
        if (!Directory.Exists(target))
        {
            Directory.CreateDirectory(target);
        }

        // Loop through for all files in a directory
        foreach (string filename in Directory.EnumerateFiles(source))
        {
            if (!File.Exists(targetFolder + filename.Substring(filename.LastIndexOf('\\'))))
            {
                attributes = File.GetAttributes(filename);

                if ((attributes & FileAttributes.ReadOnly) == FileAttributes.ReadOnly)
                {
                    //System.Windows.MessageBox.Show("File {" + filename + "} is READ ONLY");
                }
                else
                {
                    try
                    {
                        using (FileStream SourceStream = File.Open(filename, FileMode.Open))
                        {
                            using (FileStream DestinationStream = File.Create(target + filename.Substring(filename.LastIndexOf('\\'))))
                            {
                                await SourceStream.CopyToAsync(DestinationStream);
                                filesRemaining--;
                            }
                        }
                    }
                    catch (UnauthorizedAccessException)
                    {
                    }
                }
            }
        }

        // Loop through each subdirectory in the current directory and recursively call the
        // copyEverything() method using the subdirectory's full name and the name of the
        // target folder plus the subdirectory folder name
        foreach (DirectoryInfo subdir in dirs)
        {
            foldersRemaining--;
            string temppath = System.IO.Path.Combine(target, subdir.Name);
            copyEverything(subdir.FullName, temppath);
        }
    }

我能做些什么来让它在不阻塞主线程的情况下工作吗?

2 个答案:

答案 0 :(得分:1)

你还在主线程上做了一堆IODirectory.ExistFile.Exist等等......你可能想避免在主线程上做整件事

因此,一个简单的解决方案是添加一个新方法:

private void copyEverythingAsync(string source, string target)
{
  Task.Run(()=> copyEverything(source, target));
}

然后从async/await方法中移除copyEverything

这会将操作移到ThreadPool的新线程上,而不会阻止主线程。

答案 1 :(得分:0)

简单地标记方法async不会使其async,您需要await非UI /阻止代码。 await是您的异步​​代码所在的位置,通常位于Task

不在await中的所有代码都将在调用线程的上下文中运行(在您的情况下为main)。因此,即使您await复制了该副本,您也应该await整个块,使用已指定的Task