我正在开发 Blazor 项目。
我尝试创建一个异步函数来从目录中获取“.avi”和“.mkv”文件。但是,当我尝试访问该页面而不是看到“正在加载...”消息时,需要花费一些时间才能一次性获得所有结果。
这是我的服务代码:
namespace FilesScanner
{
public class FilesScannerService
{
public async Task<IEnumerable<FileInfo>> GetFilesAsync(string path,
EnumerationOptions options, string[] extensions)
{
DirectoryInfo dir = new(path);
return await Task.Run(() => extensions.SelectMany(x => dir.EnumerateFiles(x, options)
.Where(f => !f.Attributes.HasFlag(FileAttributes.Hidden))));
}
}
}
有 Blazor 页面的代码,我在其中调用上述函数:
using FilesScanner;
using Microsoft.AspNetCore.Components;
namespace MovieLibrary.Pages
{
public partial class Files
{
[Inject] private FilesScannerService _scannerService { get; set; }
public IEnumerable<FileInfo> FilesInfos { get; set; }
protected override async Task OnInitializedAsync()
{
string path = @"C:\Users\username\Videos";
string[] extensions =
{
"*.avi",
"*.mkv"
};
EnumerationOptions opts = new()
{
IgnoreInaccessible = true,
RecurseSubdirectories = true
};
FilesInfos = await _scannerService.GetFilesAsync(path, opts ,extensions);
}
}
}
最后是我显示结果的代码:
@page "/files"
@using System.IO;
<h3>Movies</h3>
@if (FilesInfos is not null)
{
try
{
int i = 1;
foreach (FileInfo file in FilesInfos)
{
<p><span style="font-weight:700">@i :</span> @Path.GetFileNameWithoutExtension(@file.Name)</p>
i++;
}
}
catch (UnauthorizedAccessException ex)
{
<p>@ex.Message</p>
}
}
else
{
<h2>LOADING...</h2>
}
我是否误解了异步函数?
GetFilesAsync
返回 Task<IEnumerable<FileInfo>>
。假设您的意图是异步完成所有工作,那就是一个问题。这项工作不是作为完成 Task<T>
的一部分完成的,而是作为枚举 IEnumerable<T>
的一部分完成的。如果您想将所有工作卸载到 ThreadPool
,请确保将该方法的返回类型更改为 Task<FileInfo[]>
(返回 Task
数组的 FileInfo
)。数组(和列表)被具体化。可枚举序列通常不是,因为它们可以通过延迟执行来实现。