我知道这个问题已被问过很多次,但我找不到适合我的答案。
我正在编写 Xamarin Forms 应用程序。在 Android 项目中我需要重写这个方法:
public override bool OnJsConfirm(WebView view, string url, string message, JsResult result)
很遗憾,我无法使方法异步。
在那个方法中我想调用另一个方法:
public static Task<bool> DisplayAlert(string title, string message, string accept, string cancel)
{
var tcs = new TaskCompletionSource<bool>();
Device.BeginInvokeOnMainThread(async () =>
{
var result = await MainPage.DisplayAlert(title, message, accept, cancel);
tcs.SetResult(result);
});
return tcs.Task;
}
MainPage.DisplayAlert()
需要在我的方法确保的 UI 线程上调用。
我已经尝试调用我的 DisplayAlert
来自同步OnJsConfirm
具有这些变体的方法:
//bool success = UI.DisplayAlert(title, message, ok, cancel).Result; // hangs !!!
//bool success = UI.DisplayAlert(title, message, ok, cancel).WaitAndUnwrapException(); // hangs !!! WaitAndUnwrapException is in Nito.AsyncEx.Synchronous
//bool success = Nito.AsyncEx.AsyncContext.Run(() => UI.DisplayAlert(title, message, ok, cancel)); // hangs !!!
//bool success = TaskEx.Run(() => UI.DisplayAlert(title, message, ok, cancel)).Result; // hangs !!!
//bool success = Task.Run(() => UI.DisplayAlert(title, message, ok, cancel)).Result; // hangs !!!
//bool success = Task.Run(async () => await UI.DisplayAlert(title, message, ok, cancel)).Result; // hangs !!!
bool success = Task.Run(async () => await UI.DisplayAlert(title, message, ok, cancel).ConfigureAwait(false)).Result; // hangs !!!
我采纳了来自 this answer 的使用 Nito.AsyncEx 的建议Stephen Cleary 对类似问题的回答。
我也已经尝试添加 .ConfigureAwait(false)
到 await MainPage.DisplayAlert(...)
,但这也没有用。
当我在 await MainPage.DisplayAlert
处设置断点时行,然后它在除最后两个变体之外的所有变体中都被击中,然后当我按下 F10 时,VS2015 停止并显示此调用堆栈:
不过也不异常(exception)。该应用程序只是挂起。
有人知道我如何调用我的异步方法吗?
最佳答案
OnJsConfirm的返回值仅表示您是否将处理确认对话框。所以你需要返回 true 并异步完成剩下的事情。如果您的 DisplayAlert
返回,您可以根据任务的结果。
public override bool OnJsConfirm(WebView view, string url, string message, JsResult result)
{
DisplayAlert("Really?", message, "OK", "Cancel").ContinueWith(t => {
if(t.Result) {
result.Confirm();
}
else {
result.Cancel();
}
});
return true;
}
public static Task<bool> DisplayAlert(string title, string message, string accept, string cancel)
{
var tcs = new TaskCompletionSource<bool>();
Device.BeginInvokeOnMainThread(async () =>
{
var result = await MainPage.DisplayAlert(title, message, accept, cancel);
tcs.SetResult(result);
});
return tcs.Task;
}
关于c# - 尝试同步调用异步方法时出现死锁,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36335859/