【问题标题】:How to use async/await correctly to display Xamarin Forms ActivityIndicator如何正确使用 async/await 来显示 Xamarin Forms ActivityIndi​​cator
【发布时间】:2018-02-14 07:46:54
【问题描述】:

我有在选择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;
}

所以:

  • buildThisListSelectedList 属性更改时被调用。
  • buildThisList 调用 buildBnBList 这是一个耗时的过程。
  • buildBnBList 中没有任何异步完成的内容。
  • StatusBarIsVisible 绑定到 ActivityIndicatorIsVisibleIsRunning

如何编写代码以使执行 buildBnBList 不会阻塞 UI 线程?

【问题讨论】:

    标签: c# asynchronous xamarin.forms portable-class-library


    【解决方案1】:

    是的,您使用异步代码混合阻塞 (.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,则 ActivityIndi​​cator 正在旋转。当我单击列表项时,微调器会停止,并且 UI 中不会发生任何其他事情,直到 OnListSelected 完成。此时 ActivityIndi​​cator 再次开始旋转,并且我选择的项目被突出显示。
    猜你喜欢
    • 1970-01-01
    • 2017-11-20
    • 2017-08-28
    • 2019-06-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多