微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

c# – 在异步方法完成之前,UI不会更新

在我的项目中,我想显示进度指示器,从Web服务检索数据并隐藏进度指示器.如果我这样做,我目前必须等到我从webservice检索数据,然后立即更新带有结果的UI.但进度指标从未出现过.所以看来,我正在UI线程上工作或阻塞.但是哪里?

这是我的代码的简单版本:

SomePage的

private async void OnItemSelected(object sender,selecteditemchangedEventArgs e)
{
    await ShowDetailView();
}

private async Task ShowDetailView()
{
    var view = new MyView();
    this.detailView = view;
    await view.LoadContent();
}

SomeView

public async Task LoadContent()
{
    var success = await LoadData();
    if (success)
    {
        Show@R_360_4045@ion();
    }
}

public async Task<bool> LoadData()
{
    try
    {
        ShowLoadingProcess();
        await Task.Delay(5000);
        this.itemList = await WebService.Instance.GetData();

        return true;
    }
    catch (Exception ex)
    {
        System.Diagnostics.Debug.WriteLine(ex.Message);
        return false;
    }
    finally
    {
        HideLoadingProcess();
    }
}

private void Show@R_360_4045@ion()
{
    Device.BeginInvokeOnMainThread(() =>
    {
        this.grid.Clear();

        foreach(var item in this.itemList)
        {
            GridItem contentItem = new GridItem(item);
            this.grid.Children.Add(contentItem);
        }
    }
}

private void ShowLoadingProcess()
{
    Device.BeginInvokeOnMainThread(() => BringProgressIndicatorToFront());
}

private void HideLoadingProcess()
{
    Device.BeginInvokeOnMainThread(() => BringProgressIndicatorToBack());
}

我尝试了不同的东西,我在UI和后台线程之间失去了同步.例如.在LoadData()完成之前调用了Show@R_360_4045@ion().

有人能给我一个关于这里有什么问题的暗示吗?

解决方法

我不完全确定为什么你的代码按照它的方式行事,但是你应该考虑到Device.BeginInvokeOnMainThread()没有给出关于何时执行动作的任何承诺.在内部,它执行以下操作:

// Simplified
s_handler = new Handler(Looper.MainLooper);
s_handler.Post(action);

它将您的操作传递给消息队列,然后在将来的未知时间点执行操作.

但是,我建议您重新考虑应用程序的体系结构.通过利用MVVM模式和数据绑定,您可以非常轻松地控制进度指示器的可见性.

viewmodel中,您将拥有以下内容

private bool isBusy;

public bool IsBusy() {
    get { return isBusy; }
    set { SetProperty(ref isBusy,value); }
}

在具有上述viewmodel作为其BindingContext的View中,您将具有以下内容

<ActivityIndicator IsRunning="{Binding IsBusy}" IsVisible="{Binding IsBusy}" />

现在,无论何时开始长时间运行操作,只需将isBusy更改为true,View就会自动显示由于绑定而运行的ActivityIndi​​cator.

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。

相关推荐