隐藏的异步函数

本文关键字:函数 异步 隐藏 | 更新日期: 2023-09-27 18:28:18

我正在尝试创建一个库,它只有一个公共函数,它返回一个枚举。根据我的需求,为其提供动力的私有函数,由于android平台的原因,必须是异步的。我想做的是将唯一的公共函数作为非异步函数使用。我知道这可能会违反直觉,但我有自己的理由。就函数的使用者而言,他们以前总是必须以同步的方式运行代码,现在这一要求没有改变,因为它被封装在一个更高效的库中。我不想让他们做等待的方法。他们不必知道,这就是幕后发生的事情。

以下是我到目前为止所拥有的,但我正在与公共方法作斗争:

public enum DialogResult
{
    Button1 = 1,
    Button2 = 2,
    Button3 = 3,
}
class MsgBox
{
    public  DialogResult Show(String Title, String Caption, Context context)
    {

    }
    private async Task<DialogResult> ShowAsync(String Title, String Caption, Context context)
    {
        return await BuildAsync(Title, Caption, context);
    }
    private Task<DialogResult> BuildAsync(String Title, String Caption,Context context)
    {
        var r = new TaskCompletionSource<DialogResult>();
        new AlertDialog.Builder(context)
        .SetPositiveButton("Yes", (sender, args) =>
        {
            // User pressed yes
            r.SetResult(DialogResult.Button1);
        })
        .SetNegativeButton("No", (sender, args) =>
        {
            // Do nothing
            r.SetResult(DialogResult.Button2);
        })
        .SetMessage(Caption)
        .SetTitle(Title)
        .Show();
        return r.Task;
    }
}

总之;我需要这个公共函数在它从ShowAsync返回后只返回我的普通DialogResult,而不需要用wait调用它自己。

隐藏的异步函数

最简短、最好的答案是"你不能"。考虑一下您正在尝试做的事情:您的代码需要使用API,该API需要在完成之前将执行返回到UI线程上的消息循环,但调用您的代码的代码需要阻止UI线程直到您的代码完成。这是一个逻辑上不可能的设计。

然而,你可以使用一些技巧来迫使它发挥作用。一种选择是将工作卸载到另一个线程;然而,这在您的情况下不起作用,因为您使用的API需要在UI线程上运行。剩下的破解方法是运行嵌套的消息循环。

运行嵌套消息循环有一个非常严重的问题:可重入性。从本质上讲,一旦有了嵌套的消息循环,客户的整个应用程序就需要处理可重入性。这就是为什么"DoEvents是邪恶的"。这是向客户提出的一个巨大要求,解释和支持要比仅仅制作方法async复杂得多。