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

时间:2016-03-31 14:10:40

标签: 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;
}

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

我已尝试使用这些变体从同步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 !!!

我使用Stephen Cleary的this answer中的Nito.AsyncEx提出了类似问题的建议。

我也尝试将.ConfigureAwait(false)添加到await MainPage.DisplayAlert(...),但这也无效。

当我在await MainPage.DisplayAlert行设置一个断点时,除了最后两个变种之外它都被击中了,当我按下F10时,VS2015停止了这个调用堆栈: enter image description here

但也没有例外。该应用程序只是挂起。

有人知道,我怎么可以调用我的异步方法?

1 个答案:

答案 0 :(得分:2)

OnJsConfirm的返回值仅表示您是否将处理确认对话框。因此,您需要返回true并以异步方式执行其余操作。如果您的"1"返回,则可以在DisplayAlert上致电Confim()Cancel(),具体取决于任务的结果。

JsResult