如何正确使用异步/等待显示Xamarin表单活动指示器
问题描述:
我有选择ListView
项目时执行的代码。由于此代码可能需要很长时间才能执行,因此我想在运行时显示ActivityIndicator
。如何正确使用异步/等待显示Xamarin表单活动指示器
我已阅读了大量有关ActivityIndicator
的帖子,我相信我已将它正确设置。我很确定我的问题是由于UI在运行过程中完全冻结导致运行代码阻塞了UI线程。
我已经通过每一个变化,我已经能够找到使用异步/等待没有运气,所以我假设我仍然在做一些不正确的事情。
这里是我的代码:
private ListItem selectedList;
public ListItem SelectedList
{
get
{
return selectedList;
}
set
{
if (selectedList != value)
{
var oldValue = selectedList;
selectedList = value;
buildThisList();
}
}
}
private async void buildThisList()
{
StatusBarIsVisibile = true;
ThisList = Task.Run(async() =>
{
return await buildBnBList(SelectedList, selectedLocation,
thisYearList.ListId)
.ConfigureAwait(false);
}).Result; // 1.8 seconds
StatusBarIsVisibile = false;
ThisList.MainVM = this;
ThisList.BuildView();
PIShowListHeaderText = SelectedList.Title.Trim();
}
private async Task<BnBList> buildBnBList(ListItem pSelectedList, State pselectedLocation, int pListId)
{
BnBList newList = new BnBList(pSelectedList, pselectedLocation, pListId);
List<BirdsnBflysMaster> bbfList =
App.BnBRepo.GetBirdsnBflys(selectedList.ListType); // 1.3 seconds
Lists parentList = App.BnBRepo.GetAList(SelectedList.ListId); // .5 seconds
BnBItem newBnBItem;
foreach (BirdsnBflysMaster bbf in bbfList) // .4 seconds
{
newBnBItem = new BnBItem(parentList, bbf, selectedLocation, newList, thisYearList.ListId);
newList.ListAll.Add(newBnBItem);
if (newBnBItem.ListTypeID == "Bird")
{
...
}
else
{
...
}
}
return newList;
}
所以:
-
buildThisList
被调用时SelectedList
属性更改。 -
buildThisList
来电buildBnBList
这是耗时的过程。 -
buildBnBList
没有任何异步完成。 -
StatusBarIsVisible
与ActivityIndicator
的IsVisible
和IsRunning
都结合。
我该如何编码,以便执行buildBnBList
不会阻塞UI线程?
答
是的你是一个混合阻塞(.Result
)与异步代码,可能导致死锁。应该避免使用async void
,除非在偶数处理程序中。
那么为什么不这样做呢?
创建事件和事件处理程序。
public event EventHandler ListSelected = delegate { }
现在应该允许您创建一个事件处理程序
private async void OnListSelected(object sender, EventArgs e) {
StatusBarIsVisibile = true;
ThisList = await buildBnBList(SelectedList, selectedLocation, thisYearList.ListId);
StatusBarIsVisibile = false;
ThisList.MainVM = this;
ThisList.BuildView();
PIShowListHeaderText = SelectedList.Title.Trim();
}
你显然会订阅事件(当然在生命周期的早期)
this.ListSelected += OnListSelected;
并根据需要提高事件
private ListItem selectedList;
public ListItem SelectedList {
get {
return selectedList;
}
set {
if (selectedList != value) {
var oldValue = selectedList;
selectedList = value;
OnListSelected(this, EventArgs.Empty);
}
}
}
感谢您的意见。我想我明白你的建议。我在我的代码中实现了它,但它没有任何区别。如果我在运行之前设置了StatusBarIsVisibile = true,则ActivityIndicator正在旋转。当我点击一个列表项时,微调框会停止,在用户界面中没有任何事情发生,直到完成OnListSelected。此时ActivityIndicator再次开始旋转,我选中的项目被突出显示。 – DaveS