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);
            }
        }
    }
}

我猜问题是在所有异步复制完成之前应用程序退出,但我不确定如何防止这种情况。我已经添加了代码来等待每个副本完成复制,然后再继续,但感觉它违背了异步工作的要点!

是否有一种方法可以使这个工作,以便所有的文件副本可以并行执行,然后要么等待每个副本完成之前关闭应用程序,或允许应用程序关闭而不终止复制操作?

CopyToAsync创建零长度文件(因为应用程序正在关闭)

您使用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
}
相关文章: