是否可以等待Device.BeginInvokeOnMainThread代码完成(使用UI调用的结果继续进行后台工作) [英] Is it possible to wait for Device.BeginInvokeOnMainThread code to finish (continue background work with results of a UI call)

查看:191
本文介绍了是否可以等待Device.BeginInvokeOnMainThread代码完成(使用UI调用的结果继续进行后台工作)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我的代码中,我有一个名为"ShowMessageBoxAsync"的任务.我想使用此代码向用户显示(并等待)DisplayAlert并返回结果.像这样:var messageBoxResult = await View.ShowMessageBoxAsync("This is a error");

In my code I have a task called "ShowMessageBoxAsync". I want to use this code to show (and await) the DisplayAlert to the user and return the result. Like this: var messageBoxResult = await View.ShowMessageBoxAsync("This is an error");

ShowMessageBoxAsync的代码为:

The code for the ShowMessageBoxAsync is:

public async System.Threading.Tasks.Task<bool> ShowMessageBoxAsync(string message)
{
    var result = false;
    Device.BeginInvokeOnMainThread(async () =>
    {
        result = await DisplayAlert("Error", message, "OK", "Cancel");
    });
    return result;
}

在我添加Device.BeginInvokeOnMainThread之前,该任务给了我一个异常,提示它未在主/UI线程上运行.因此,在添加BeginInvokeOnMainThread之后,它开始正常工作.但是,问题在于代码直接进入结果,而没有等待"await DisplayAlert"的结果.

Before I added the Device.BeginInvokeOnMainThread, the task gave me an Exception that it wasn't running on the main/UI thread. So after adding BeginInvokeOnMainThread, it started to work without exceptions. The problem, however, is that the code goes directly to the result, without waiting for the result of the "await DisplayAlert".

是否只有在Device.BeginInvokeOnMainThread代码完成后才返回结果"的值?

Is it possible return the value of "result" only after the Device.BeginInvokeOnMainThread code finishes?

我对此进行了一些研究,有人建议使用TaskCompletionSource,但这会阻塞UI线程,并且DisplayAlert根本不会显示.

I did some research about it and someone suggested to use a TaskCompletionSource, but this blocks the UI thread and the DisplayAlert doesn't show up at all.

推荐答案

我对此进行了研究,有人建议使用TaskCompletionSource

I did some research about it and someone suggested to use a TaskCompletionSource

那是正确的解决方案. TaskCompletionSource充当Task的完成者".在这种情况下,此Task表示用户交互,因此您希望UI线程上的代码完成Task的工作,而后台线程上的代码则要(a)等待`Task.

That is the correct solution. TaskCompletionSource acts as a "completer" for a Task. In this case, this Task is representing the user interaction, so you want the code on the UI thread to do the completing of the Task, and the code on the background thread to (a)wait for the `Task.

所以,像这样:

public Task<bool> ShowMessageBoxAsync(string message)
{
  var tcs = new TaskCompletionSource<bool>();
  Device.BeginInvokeOnMainThread(async () =>
  {
    try
    {
      var result = await DisplayAlert("Error", message, "OK", "Cancel");
      tcs.TrySetResult(result);
    }
    catch (Exception ex)
    {
      tcs.TrySetException(ex);
    }
  });
  return tcs.Task;
}

这应该让您暂时畅通无阻.但是,一个更好的长期解决方案是让您的后台线程逻辑采用某种与UI交互"的界面,如下所示:

This should get you unblocked for now. However, a better long-term solution would be to have your background thread logic take some kind of "interact with the UI" interface like this:

public interface IAskUser
{
  Task<bool> AskUserAsync(string message);
}

具有与上述类似的Xamarin-Forms特定实现.

with a Xamarin-Forms-specific implementation similar to above.

这样,您的后台线程逻辑就不会绑定到特定的UI,并且可以更轻松地进行单元测试和重用.

That way, your background thread logic isn't tied to a specific UI, and can be more easily unit tested and reused.

这篇关于是否可以等待Device.BeginInvokeOnMainThread代码完成(使用UI调用的结果继续进行后台工作)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆