我选择了ListView项目时会执行代码。由于此代码可能要花费大量时间才能执行,因此我想在运行时显示ActivityIndicator

我已经阅读了很多有关ActivityIndicator的帖子,并且我相信我已经正确设置了它。我很确定我的问题是由于正在运行的代码阻塞了UI线程,因为UI在此过程中完全冻结了。

我已经尝试过通过使用async / await而没有运气的所有变化,所以我假设我仍然在做错误的事情。

这是我的代码:

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绑定到IsVisibleIsRunningActivityIndicator


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

关于c# - 如何正确使用async/await来显示Xamarin Forms ActivityIndi​​cator,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/46064707/

10-12 14:41