如何正确使用异步/等待显示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没有任何异步完成。
  • StatusBarIsVisibleActivityIndicatorIsVisibleIsRunning都结合。

我该如何编码,以便执行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); 
     } 
    } 
} 
+0

感谢您的意见。我想我明白你的建议。我在我的代码中实现了它,但它没有任何区别。如果我在运行之前设置了StatusBarIsVisibile = true,则ActivityIndi​​cator正在旋转。当我点击一个列表项时,微调框会停止,在用户界面中没有任何事情发生,直到完成OnListSelected。此时ActivityIndi​​cator再次开始旋转,我选中的项目被突出显示。 – DaveS