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

标签 c# xamarin xamarin.forms async-await ui-thread

在我的项目中,我想显示进度指示器,从网络服务检索数据并隐藏进度指示器。如果我这样做,我目前必须等到我从 web 服务检索数据,然后立即更新包含结果的 UI。但是进度指示器永远不会出现。看来,我正在 UI 线程上工作或阻塞。但是在哪里呢?

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

一些页面

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

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

一些 View

public async Task LoadContent()
{
    var success = await LoadData();
    if (success)
    {
        ShowInformation();
    }
}

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 ShowInformation()
{
    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 和后台线程之间不同步。例如。 ShowInformation()LoadData() 完成之前被调用。

有人可以提示我这里出了什么问题吗?

最佳答案

我不完全确定为什么您的代码会按照它的方式运行,但您应该考虑到 Device.BeginInvokeOnMainThread() 不会对何时执行操作做出任何 promise 。它在内部执行以下操作:

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

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

但是,我建议您重新考虑应用程序的架构。通过利用 MVVM 模式和数据绑定(bind),您将能够非常轻松地控制进度指示器的可见性。

在 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(由于绑定(bind))。

关于c# - 在异步方法完成之前,UI 不会更新,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42837125/

相关文章:

c# - .NET IExtenderProvider (C#)

c# - 如何创建动态类型 List<T>

c# - 绑定(bind)带参数的点击函数

xamarin - 颜色转换器绑定(bind)未被调用

c# - 过滤对象 C# 的 ObservableCollection

c# - 如何更改只读变量的值?

c# - DreamHost PS 上的 ASP.NET Model View Controller 应用程序

Xamarin 用户界面测试。取控件的背景色ios

macos - 如何在 OS X 上使用 mdtool 构建 .sln 文件

xamarin - 系统.DllNotFoundException : java-interop