我正在尝试创建一个只有一个公共函数的库,它返回一个枚举 . 根据我的要求提供支持的私有函数必须是异步的,因为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 回答
最短和最好的答案是"you can't" . 想想你要做的事情:你的代码需要使用一个API,它需要在完成之前将执行返回到UI线程上的消息循环,但调用代码的代码需要阻止UI线程,直到你的代码完成 . 这是一个逻辑上不可能的设计 .
但是,您可以使用a couple hacks来强制它起作用 . 一种选择是将工作卸载到另一个线程;但是,它赢得了使用UI线程上运行的需求 . 剩下的hack是运行嵌套的消息循环 .
运行嵌套消息循环有一个非常严重的问题:重入 . 基本上,一旦你有一个嵌套的消息循环,你的客户的整个应用程序需要处理重入 . 这就是为什么“
DoEvents
是邪恶的” . 这对于推动客户来说是一个巨大的要求,解释和支持要比制定方法更加复杂async
.