在异步方法中显示进度对话框

Posted

技术标签:

【中文标题】在异步方法中显示进度对话框【英文标题】:showing progress Dialog inside an async method 【发布时间】:2016-11-11 19:35:43 【问题描述】:

我想在异步事件侦听器方法中显示进度对话框。现在,UI 组件仅在异步方法执行完成后才可见。这是我的代码:

async void process_Click(object sender, EventArgs e)
    

        launchRingProgressDialog();

        var comp = await Start();

    

public void launchRingProgressDialog()
    
        Activity.RunOnUiThread(() =>
        
            ProgressDialog ringProgressDialog = ProgressDialog.Show(Activity, "Processing", "Please wait", true);
            ringProgressDialog.SetCancelable(true);
        );
    

当我在异步方法之外调用方法launchRingProgressDialog()时显示进度对话框,但在异步方法运行时不显示。如何使异步方法不阻塞 UI 组件?

编辑

据我了解,异步方法在 UI 线程内运行,因此不需要 RunOnUiThread。我已将代码更改如下,但我仍然面临同样的问题。

 async void process_Click(object sender, EventArgs e)
    

        ringProgressDialog = ProgressDialog.Show(Activity, "Processing", "Please wait", true);

        var comp = await Start();

        ringProgressDialog.Dismiss();

        

【问题讨论】:

【参考方案1】:

在从 UI 线程调用的 async 方法中运行 UI 代码时(例如,像您在代码中一样的按钮单击等 UI 事件),您不需要使用 RunOnUiThread。这是因为当 awaited Task 完成时,方法会在调用线程上继续,在本例中是 UI 线程。

例如,看看下面的代码,它是我的一个应用程序的一部分,它成功运行并获得了预期的结果:

private async void ExecuteSearchButton_Click(object sender, System.EventArgs e)

    spinner.Visibility = ViewStates.Visible;

    CollectionFeed feed = await CollectionFeed.SearchAsync(searchEditText.Text);

    GenericAdapter<Collection, CollectionViewHolder> adapter = 
            new GenericAdapter<Collection, CollectionViewHolder>(Resource.Layout.CollectionRecyclerViewItem,
                                                                 feed.Results, view => new CollectionViewHolder(view));

    searchResultRecyclerView.SetAdapter(adapter);

    spinner.Visibility = ViewStates.Gone;

spinner 在点击时出现,在数据加载到 RecyclerView.Adapter(也成功加载)时消失。

您编辑的方法将是

public void launchRingProgressDialog()

    ProgressDialog ringProgressDialog = ProgressDialog.Show(Activity, "Processing", "Please wait", true, true);

它使用this ProgressDialog constructor 删除SetCancelable 调用。

【讨论】:

我知道异步方法在 UI 线程中运行,我不需要 RunOnUiThread。我在异步操作运行之前启动对话框并在等待任务之后将其关闭,但这并没有真正起作用。只有在整个异步方法执行完毕后,对话框或任何其他 UI 组件才可见。也许我应该在异步方法中启动一个新线程并在其中运行异步操作? @AhmedMujtaba 如果我修改我作为示例发布的代码以包含ProgressDialog,它会在正确的时间出现并被取消。您的async 操作是否持续时间很短(async 方法时,Xamarin 会导致应用程序出现小暂停。 我已经通过在 Task.Run 中运行异步操作来解决它。我还有一个小问题需要解决。我想在第一个对话框被关闭后启动一个新的 ProgressDiaglog,但第二个对话框仅在异步方法执行完成后才显示。这是因为 UI 线程上的活动过多,它会阻塞其他 UI 操作吗? 您的异步方法实际上是异步的(即它们有一个await 或返回一个可运行的Task)还是为了异步而使用async?如果他们真的是async,那么应该没有任何东西阻塞 UI 线程。 我有 2 个异步方法,当按下按钮时调用它,另一个在单独的线程中运行进程。你可以从这里查看我的完整代码pastie.org/10902657

以上是关于在异步方法中显示进度对话框的主要内容,如果未能解决你的问题,请参考以下文章

如果异步任务被解除,则重新显示进度对话框

在 AsyncTask 中显示进度对话框

在异步任务中给出异常的进度对话框[重复]

尝试连接到服务器时带有异步任务的进度条

使用异步任务制作进度对话框

Android项目实战(三十一):异步下载apk文件并安装(非静默安装)