c# - 尝试同步调用异步方法时出现死锁

标签 c# android multithreading asynchronous xamarin

我知道这个问题已被问过很多次,但我找不到适合我的答案。

我正在编写 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 停止并显示此调用堆栈: enter image description here

不过也不异常(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/

相关文章:

java - 上下文在Fragment中返回null

multithreading - 线程已完成但循环未结束

ios - 从并发队列调用 dispatch_sync - 它会完全阻塞吗?

c# - LINQ OrderBy 有一个异常(exception)

c# - 每次触发Form.Load事件

java - E/RecyclerView : No adapter attached; skipping layout -- when making a todo list app

android - 如何控制android中的ontouch功能?

python - 在完成之前杀死 python 中的线程

c# - 如何在c# wpf应用程序中绘制具有不同z索引的多条线

c# - System.Security.VerificationException : Operation could destabilize the runtime.(亚音速 2.2)