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