已解决,感谢戴夫的回答。
他向我展示了如何停止async
任务,该任务回答了我的第二个问题。
要过滤不需要的文件夹,我已更改SkipDirectory(string)
来检查目录的路径(如果您有更好的解决方案,我希望听到它)。
该函数写在底部。
我想知道C#中是否有一种复制文件夹的方法,但是带有一些过滤器。即不包括某些子文件夹。
如何在不使程序卡死的情况下执行此操作。 我发现的当前代码会复制该文件夹及其所有子文件夹,但该程序会卡住一秒钟。
我发现的另一个代码使用async
方法,它解决了突然暂停的问题,但是我无法在中间停止它(必须有一个选项来停止任务)
总而言之,我需要做两件事:
1)复制一个文件夹,不包括某些子文件夹。
2)复制文件夹而不会使程序卡住
这是我使用的第一个代码(没有async
):
private void Copy(string sourcePath, string destinationPath)
{
foreach (string dirPath in Directory.GetDirectories(sourcePath, "*",
SearchOption.AllDirectories))
{
if (SkipDirectory(dirPath))
{
continue;
}
Debug.Log(dirPath);
Directory.CreateDirectory(dirPath.Replace(sourcePath, destinationPath));
}
//Copy all the files & Replaces any files with the same name
foreach (string newPath in Directory.GetFiles(sourcePath, "*.*",
SearchOption.AllDirectories))
{
try
{
FileInfo file = new FileInfo(newPath);
if (SkipDirectory(file.DirectoryName)) continue;
text += ("Copying " + newPath + "\n\n");
File.Copy(newPath, newPath.Replace(sourcePath, destinationPath), true);
}
catch (System.Exception)
{
}
}
}
还有async
代码:
private async System.Threading.Tasks.Task Copy(string startDirectory, string endDirectory)
{
foreach (string dirPath in Directory.GetDirectories(startDirectory, "*", SearchOption.AllDirectories))
{
if (!SkipDirectory(dirPath))
{
Debug.Log("Creating directory " + dirPath);
Directory.CreateDirectory(dirPath.Replace(startDirectory, endDirectory));
foreach (string filename in Directory.EnumerateFiles(dirPath))
{
try
{
using (FileStream SourceStream = File.Open(filename, FileMode.Open))
{
using (FileStream DestinationStream = File.Create(filename.Replace(startDirectory, endDirectory)))
{
text += ("Copying " + filename + "\n\n");
await SourceStream.CopyToAsync(DestinationStream);
}
}
}
catch (System.Exception e)
{
Debug.LogWarning($"Inner loop:\t{filename}\t{e.Message}");
}
}
}
else
{
Debug.Log("Skipping " + dirPath);
}
}
foreach (string filename in Directory.EnumerateFiles(startDirectory))
{
try
{
using (FileStream SourceStream = File.Open(filename, FileMode.Open))
{
using (FileStream DestinationStream = File.Create(endDirectory + filename.Substring(filename.LastIndexOf('\\'))))
{
await SourceStream.CopyToAsync(DestinationStream);
}
}
}
catch (System.Exception e)
{
Debug.LogWarning($"Outter loop:\t{filename}\t{e.Message}");
}
}
}
SkipDirectory(string)
函数仅根据文件夹名称返回true / false:
private bool SkipDirectory(string dirPath)
{
dirPath = dirPath.ToLower();
string[] namesToSkip = { "library", "temp", "obj", ".vs" };
foreach (string nameToSkip in namesToSkip)
{
// I now check the path of the folder to see if it matches.
string unwantedPath = $@"{projectPath}\{nameToSkip}".ToLower();
if (dirPath.StartsWith(unwantedPath))
{
return true;
}
}
return false;
}
答案 0 :(得分:1)
因此您可以将CancellationToken传递给您的方法,并将其用于请求取消
您的代码已更新为可以使用取消令牌
private async Task Copy(string startDirectory, string endDirectory, CancellationToken ct)
{
foreach (string dirPath in Directory.GetDirectories(startDirectory, "*", SearchOption.AllDirectories))
{
//Here we check if cancellation has been requesting if it has it will throw an exception (you can also check the IsCancellationRequested property and return)
ct.ThrowIfCancellationRequested();
if (!SkipDirectory(dirPath))
{
Debug.Log("Creating directory " + dirPath);
Directory.CreateDirectory(dirPath.Replace(startDirectory, endDirectory));
foreach (string filename in Directory.EnumerateFiles(dirPath))
{
try
{
using (FileStream SourceStream = File.Open(filename, FileMode.Open))
{
using (FileStream DestinationStream = File.Create(filename.Replace(startDirectory, endDirectory)))
{
await SourceStream.CopyToAsync(DestinationStream,81920, ct); //Pass cancellation token in to here and this can also handle cancellation
}
}
}
catch (OperationCanceledException)
{
throw;
}
catch (System.Exception e)
{
Debug.LogWarning($"Inner loop:\t{filename}\t{e.Message}");
}
}
}
else
{
Debug.Log("Skipping " + dirPath);
}
}
foreach (string filename in Directory.EnumerateFiles(startDirectory))
{
//Here we check if cancellation has been requesting if it has it will throw an exception (you can also check the IsCancellationRequested property and return)
ct.ThrowIfCancellationRequested();
try
{
using (FileStream SourceStream = File.Open(filename, FileMode.Open))
{
using (FileStream DestinationStream = File.Create(endDirectory + filename.Substring(filename.LastIndexOf('\\'))))
{
await SourceStream.CopyToAsync(DestinationStream,81920, ct); //Pass cancellation token in to here and this can also handle cancellation
}
}
}
catch(OperationCanceledException)
{
throw;
}
catch (System.Exception e)
{
Debug.LogWarning($"Outter loop:\t{filename}\t{e.Message}");
}
}
}
然后您的代码调用者可以通过执行以下操作来创建新的取消令牌
var cts = new CancellationTokenSource(); //you can also pass a value for a timeout to this ctor
var token = cts.Token;
您可以通过致电cts.Cancel()