无法从异步函数向列表添加数据——Xamarin.Forms开发问题
问题分析与解决方案
核心问题
- 异步调用未等待:构造函数中调用
GetAllfilesInSiRoDataAsync()时未使用await,导致UI初始化完成后,异步文件读取操作还未结束,Picker绑定的列表仅包含初始手动添加项。 - 集合无UI通知机制:使用
List<T>存储数据,集合元素变化时无法自动通知UI刷新,后续添加的元素无法同步到Picker。 - 不必要的后台线程:用
Task.Run包裹异步操作完全多余(PCLStorage的API本身就是异步非阻塞的),还可能引发后台线程操作UI控件的线程安全问题。
修复步骤
1. 替换集合类型为可观察集合
将List<T>改为ObservableCollection<T>,它会在元素增删时自动触发UI更新:
using System.Collections.ObjectModel; public ObservableCollection<IFile> presetFilesList = new ObservableCollection<IFile>(); public ObservableCollection<string> presetNamesList = new ObservableCollection<string>();
2. 正确处理异步初始化
构造函数无法标记为async,因此创建异步初始化方法确保等待文件读取完成:
public MainPage() { InitializeComponent(); // 添加默认选项 presetNamesList.Add("Choose a preset here"); // 调用异步初始化,用_避免未使用返回值的警告 _ = InitializePresetsAsync(); } private async Task InitializePresetsAsync() { await GetAllfilesInSiRoDataAsync(); }
3. 简化异步函数,移除多余的Task.Run
直接使用PCLStorage的异步API,避免后台线程操作UI:
private async Task<bool> GetAllfilesInSiRoDataAsync() { try { IFolder root = PCLStorage.FileSystem.Current.LocalStorage; // 避免文件夹不存在时抛出异常 IFolder folder = await root.GetFolderAsync("SiRoData", CreationCollisionOption.OpenIfExists); var siroFolder = await folder.GetFilesAsync(); foreach (IFile file in siroFolder) { presetFilesList.Add(file); // 移除文件后缀(假设后缀为4位,如.txt) string nomFichier = file.Name.Substring(0, file.Name.Length - 4); presetNamesList.Add(nomFichier); } presetPicker.ItemsSource = presetNamesList; presetPicker.SelectedIndex = 0; return true; } catch (Exception ex) { // 可添加异常处理,比如日志记录或用户提示 return false; } }
额外优化建议
- 可在
OnAppearing中执行初始化,添加判断避免重复加载:protected override async void OnAppearing() { base.OnAppearing(); // 仅当只有默认选项时加载数据 if (presetNamesList.Count == 1) { await GetAllfilesInSiRoDataAsync(); } }
内容的提问来源于stack exchange,提问作者Zartox29
相关产品推荐
相关产品推荐

