【问题标题】:Task is running to completion, even though it is not completed [closed]任务正在运行完成,即使它没有完成[关闭]
【发布时间】:2017-11-10 15:26:56
【问题描述】:

我遇到了一个问题,我似乎无法弄清楚为什么它似乎没有正确等待。

我有一个异步的递归文件副本,如下所示:

public async Task CopyFiles(string source, string destination)
{
    if (!Directory.Exists(destination))
    {
        Directory.CreateDirectory(destination);
    }

    var info = new DirectoryInfo(source);

    foreach (var file in info.EnumerateFiles())
    {
        Progress.Report(new Counter { Files = 1, FileSize = file.Length, Log = $"Copying file {file.Name}" });
        try
        {
            var newpath = Path.Combine(destination, file.Name);
            if (File.Exists(newpath) && File.GetLastWriteTime(newpath) == file.LastWriteTime)
            {
                continue;
            }

            using (FileStream reader = new FileStream(file.FullName, FileMode.Open, FileAccess.Read))
            {
                using (FileStream writer = new FileStream(newpath, FileMode.Create, FileAccess.ReadWrite))
                {
                    await reader.CopyToAsync(writer);
                }

            }

            File.SetLastAccessTime(newpath, file.LastAccessTime);
            File.SetLastWriteTime(newpath, file.LastWriteTime);
            File.SetAttributes(newpath, file.Attributes);

        }
        catch
        {

        }
    }

    foreach (var directory in info.EnumerateDirectories())
    {
        try
        {
            await CopyFiles(directory.FullName, $"{destination}\\{directory.Name}");
        }
        catch
        {

        }
    }

该方法在 Prism 中使用 DelegateCommand 调用

        private async Task RestoreFiles()
    {
        var progress = GetProgressReporter();

        var recursion = new Recursion(progress, Environment.GetFolderPath(Environment.SpecialFolder.UserProfile));
        await recursion.CopyFiles(@"\\800CRBackup\Backups\Profiles\Beta\" + $"{Environment.UserName}", Environment.GetFolderPath(Environment.SpecialFolder.UserProfile)));

        ResetStats();
    }

运行调试器时,它认为任务已经运行完成。然而,情况似乎并非如此,因为该方法中的进度报告器减去绑定到 ViewModel 的剩余要复制的总剩余文件。

ResetStats 方法将剩余文件、剩余大小和当前日志设置为 0。

但由于递归副本仍在发生,即使它说任务已完成,它会导致我的 UI 进入负数。

我修复它的唯一方法是将递归包装到 Task.Run 中,但那时我没有必要尝试异步执行它。

我对这里发生的事情的最佳猜测是与事件处理程序中的 async void 有关,但不确定如何解决它,因为命令是 voids。

【问题讨论】:

  • 您是否遇到了一些您未在 catch 中处理的错误?在这种情况下,异步并没有什么可实现的,它可能最终会减慢应用程序的速度,因为您没有处理高并发。
  • 如果您没有创建目录的权限,代码将什么也不做。
  • 任务无异常完成,我还用try catch块包围它以抛出异常,也没有捕获到任何东西。
  • 是的,我知道如果目录创建中没有可用的权限,代码将失败,但在这种情况下,我确实有权限。代码工作正常,唯一的问题是等待的任务在它真正完成之前完成。如果它也包含在新线程中的 Task.Run 中,它也可以正常工作。
  • 我看不到任何东西async void,也看不到事件,也看不到DelegateCommand...你能发布相关代码吗?

标签: c# multithreading asynchronous concurrency prism


【解决方案1】:

问题在于 IProgress 正在刷新 UI 以至于它阻塞了 UI 线程,导致等待无法正常工作。在结果修复问题后添加延迟。

将需要使用计时器或反应方法来修复它,而不是使用创可贴修复。

【讨论】:

    猜你喜欢
    • 2016-08-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多