gpt4 book ai didi

c# - 如何防止由于IO操作期间属性快速变化而导致UI阻塞?

转载 作者:行者123 更新时间:2023-12-03 10:56:34 26 4
gpt4 key购买 nike

我正在研究某个时候删除文件夹的应用程序。为了向用户显示进度,我在View中使用了ProgressBar。因此,我的ViewModel double SetupProgressdouble SetupProgressMax具有两个属性。我会编译要删除的文件夹中包含的所有文件的列表,并且每次成功删除文件后,都会更新SetupProgress属性。我不知道要删除的文件数量。

我的代码(浓缩到重要部分):

public class ViewModel : INotifyPropertyChanged
{
public double SetupProgress
{
get; set; // Notifies about changes
}

public double SetupProgressMax
{
get; set; // Notifies about changes
}

public async Task<bool> DeleteFiles(IList<string> filesToBeDeleted)
{
bool success = true;
SetupProgressMax = filesToBeDeleted.Count;

foreach (string filePath in filesToBeDeleted)
{
success = success && await IOHelper.TryDeleteFile(filePath);

if (success)
{
// Report that one item has been processed.
_OnProgressChanged();
}
else
{
break;
}
}

return success;
}

public void _OnProgressChanged()
{
// SetupProgress is the VM property bound by the ProgressBar
SetupProgress++;
}
}

public static class IOHelper
{
public static async Task<bool> TryDeleteFile(string filePath, int tries = 3)
{
while (tries > 0)
{
try
{
FileInfo fi = new FileInfo(filePath);
if (fi.IsReadOnly)
{
fi.IsReadOnly = false;
}
fi.Delete();
return true;
}
catch (FileNotFoundException)
{
return true;
}
catch (Exception ex)
{
tries--;
if (tries == 0)
{
// Log error
}
else
{
// Log warning
}
await Task.Delay(50);
}
}

return false;
}
}

我的问题是,在删除文件时,UI线程会完全阻塞,并且仅在操作完成后才更新(所有文件都已删除)。

问题
  • UI进程被阻止的原因可能是什么?
  • 我该如何规避?


  • 更新:删除了我在发布问题之前测试过的解决方案,因为它们不起作用,甚至无法解决问题的根源。

    最佳答案

    似乎TryDeleteFile正在UI线程中执行。鉴于其当前的实现,它不是异步方法,不应返回Task,而应返回bool:

    public static bool TryDeleteFile(string filePath)
    {
    try
    {
    FileInfo fi = new FileInfo(filePath);
    if (fi.IsReadOnly)
    {
    fi.IsReadOnly = false;
    }
    fi.Delete();
    return true;
    }
    catch (FileNotFoundException)
    {
    return true;
    }
    catch (Exception ex)
    {
    // Log Exception
    return false;
    }
    }

    由于该方法缺少任何 await操作,因此完全不需要 await关键字。

    您可以使用 Task.Run在 View 模型的后台线程上调用sync方法:
    public async Task<bool> DeleteFiles(IList<string> filesToBeDeleted)
    {
    ...
    foreach (string filePath in filesToBeDeleted)
    {
    success = success && await Task.Run(() => IOHelper.TryDeleteFile(filePath));
    ...
    }
    return success;
    }

    请注意,使用异步API公开真正同步的方法被认为是不好的做法。有关更多信息,请引用 Stephen Toub's blog post

    关于c# - 如何防止由于IO操作期间属性快速变化而导致UI阻塞?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55970432/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com