隐藏的异步功能

时间:2014-10-28 13:35:03

标签: c# android asynchronous xamarin async-await

我正在尝试创建一个只有一个公共函数的库,它返回一个枚举。根据我的要求提供支持的私有函数必须是异步的,因为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,而不需要用await调用它自己。

1 个答案:

答案 0 :(得分:1)

最短和最好的答案是&#34;你不能&#34;。想想你正在尝试做什么:你的代码需要在完成之前使用需要将执行返回到UI线程上的消息循环的API,但调用代码需要的代码需要在您的代码完成之前,阻止UI线程。这是一个逻辑上不可能的设计。

但是,您可以使用a couple hacks来强制它发挥作用。一种选择是将工作卸载到另一个线程;但是,由于您使用的API需要在UI线程上运行,因此无法在您的情况下工作。剩下的黑客是运行嵌套的消息循环。

运行嵌套消息循环有一个非常严重的问题:重入。基本上,一旦你有一个嵌套的消息循环,你的客户&#39;整个应用程序需要处理重入。这就是&#34; DoEvents是邪恶的原因&#34;。这对于推动客户来说是一个巨大的要求,解释和支持要比制定方法async复杂得多。