首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >尝试同步调用异步方法时的死锁

尝试同步调用异步方法时的死锁
EN

Stack Overflow用户
提问于 2016-03-31 14:10:40
回答 1查看 2K关注 0票数 3

我知道这个问题已经问了很多次了,但我找不到一个对我有用的答案。

我在写一个Xamarin表单应用程序。在Android项目中,我需要重写这个方法:

代码语言:javascript
复制
public override bool OnJsConfirm(WebView view, string url, string message, JsResult result)

因此,不幸的是,我无法使方法异步。

在该方法中,我想调用另一个方法:

代码语言:javascript
复制
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;
}

需要在UI线程上调用MainPage.DisplayAlert(),这是我的方法所确保的。

我已经尝试使用以下变体从同步DisplayAlert方法调用我的OnJsConfirm

代码语言:javascript
复制
//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 !!!

我从Stephen的Nito.AsyncEx中得到了使用这个答案的建议,并提出了类似的问题。

我也尝试过将.ConfigureAwait(false)添加到await MainPage.DisplayAlert(...)中,但这也不起作用。

当我在await MainPage.DisplayAlert行设置一个断点时,除了最后两个变体之外,所有的断点都会被击中,然后按下F10,VS2015就停止了这个调用堆栈:

当然也不例外。应用程序就挂起来了。

有谁知道,我怎么能调用我的异步方法?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-03-31 15:03:27

如果要处理确认对话框,则OnJsConfirm的返回值仅指示。因此,您需要返回true并异步执行其余的操作。如果您的DisplayAlert返回,您可以根据任务的结果在JsResult上调用Confim()Cancel()

代码语言:javascript
复制
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;
}
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/36335859

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档