我有一种方法可以将一个目录中的所有文件和文件夹复制到另一个目录中,并且它可以递归地工作。我的问题是它阻止了主线程,我想使文件和文件夹的实际复制异步。我目前正在使用一个函数来异步复制文件,但它似乎不起作用。 这是代码:
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);
}
}
我能做些什么来让它在不阻塞主线程的情况下工作吗?
答案 0 :(得分:1)
你还在主线程上做了一堆IO
:Directory.Exist
,File.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