CopyToAsync创建零长度文件(因为应用程序正在关闭)
本文关键字:应用程序 因为 创建 文件 CopyToAsync | 更新日期: 2023-09-27 18:12:50
我正在编写一个简单的控制台应用程序,将文件从一个地方复制到另一个地方。我想异步复制。大多数情况下似乎是有效的,但是一些被复制的文件最终是零长度的文件或比它们应该的小,并且无法打开。
下面是我代码的相关部分:
static async void CopyFiles()
{
foreach (string myFileName in filenameList) // get a list of files to copy.
{
Task xx = CopyDocumentAsync(myFileName);
xx.Wait(); // without this Wait some of the files are not copied properly.
}
}
static async Task CopyDocumentAsync(string myFileName)
{
if (!String.IsNullOrEmpty(myFileName))
{
using (FileStream source = File.Open(sourcePath +"''" + myFileName, FileMode.Open))
{
using (FileStream destination = File.Create(destinationPath + "''" + myFileName))
{
await source.CopyToAsync(destination);
}
}
}
}
我猜问题是在所有异步复制完成之前应用程序退出,但我不确定如何防止这种情况。我已经添加了代码来等待每个副本完成复制,然后再继续,但感觉它违背了异步工作的要点!
是否有一种方法可以使这个工作,以便所有的文件副本可以并行执行,然后要么等待每个副本完成之前关闭应用程序,或允许应用程序关闭而不终止复制操作?
您使用async void
代替CopyFiles
,这意味着它是一个立即完成的任务。
您的父调用方法将在CopyFiles
完成运行之前返回。这就是为什么应用程序在文件复制完成之前退出。
把它改成一个可等待的方法:
static async Task CopyFiles()
然后你可以在父方法中等待调用。
如果你不能在父方法中等待调用(例如;(因为它是一个被覆盖的方法),那么您可以在任务上使用WaitAndUnwrapException。
你的函数CopyFiles被声明为async。
- 所有异步函数应该返回Task而不是void和Task
<TResult
>而不是result 唯一可能返回void的异步函数是事件处理程序。 - 如果你等待一个async函数的返回,返回值是void或者result。
- 当其他任务正在运行时,如果您无事可做,只需等待任务
- 但是,如果你确实有其他事情要做,在任务运行时做其他事情,当你需要任务的结果时等待它 你可能想要做的一件事是启动其他任务。
- 如果需要等待所有已启动的任务完成,则等待任务。WhenAll
如果你想同时复制几个文档,你的代码将如下所示:
private async void OnButton1_Clicked(object sender, ...)
{
// prevent pressing the button while the files are being copied:
this.button1.Enabled = false;
// start copying files and wait until ready
// Because this function is async, the UI remains responsive
await this.CopyFiles();
this.button1.Enabled = true;
}
// return Task instead of void!
private async Task CopyFiles()
{
List<Task> runningTasks = new List<Task>();
foreach (string myFileName in this.GetFilenameList())
{
runningTasks.Add(CopyDocumentAsync(myFileName));
}
// now that all tasks are running do other things you want to do,
// wait for all Tasks to finish:
await Task.WhenAll(runningTasks);
// now that all tasks are finished you can return
}