在等待操作完成时显示 ProgressBar

Display ProgressBar while waiting for operation to complete

在我的 MVVMCross 应用程序中,我有一个 Android ProgressBar 定义为:

<ProgressBar
    android:id="@+id/progressBar"
    style="?android:attr/progressBarStyleLarge"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:progressDrawable="@drawable/circular_progress_bar"
    android:gravity="right"
    local:MvxBind="Visibility Visibility(IsBusy)" />

在ViewModel中,点击按钮开始操作时执行的代码如下:

public void Next()
{
    IsBusy = true;

    try
    {
        //THE EXPENSIVE OPERATION
        var response = CallTimeConsumingService();

        if (response.MethodFailed)
        {
            _dialogService.DisplayAlert(this, response.Message);
            return;
        }

        ShowViewModel<ShowNextView>();
    }
    catch (Exception ex)
    {
        _dialogService.DisplayAlert(this, ex.Message);
    }

    IsBusy = false;
}

但是 ProgressBar 不会显示,除非我删除最后一个 IsBusy = false;, 但这意味着仅在 Next() 方法退出时显示(而不是在等待时)

如何在等待时显示 ProgressBar 并在导航到下一页之前禁用它?

===编辑====

结束这样做:

public void Next()
{
   async () =>
       {
           IsBusy = true;
           await DoWork();
           IsBusy = false;
       });
}

将其余代码添加到 DoWork 并等待任务

//THE EXPENSIVE OPERATION
var response = await CallTimeConsumingServiceReturningTask();

发生这种情况是因为更新 UI 的过程当前发生在与您的昂贵操作相同的线程中。在您的操作完成之前,UI 线程会被阻塞并且视觉反馈永远不会正确显示。要解决这个问题,您需要将 CallTimeConsumingService() 变成一个异步调用(使其成为 return 一个 Task<T>)并 await 以使其完成。

如果您的方法中有网络调用,则阻塞方法具有已经可以等待的异步对应方法。如果你的方法只涉及繁重的处理,你应该使用 TaskCompletionSource or Task.Run.

之前的答案是正确的,但您可以通过使 next() 方法异步来编写更简洁的代码:

public async Task Next()
{
    IsBusy = true;

    try
    {
        //THE EXPENSIVE OPERATION
        var response = await CallTimeConsumingServiceReturningTask();

        if (response.MethodFailed)
        {
            _dialogService.DisplayAlert(this, response.Message);
            return;
        }

        ShowViewModel<ShowNextView>();
    }
    catch (Exception ex)
    {
        _dialogService.DisplayAlert(this, ex.Message);
    }

    IsBusy = false;
}