2016-03-31 3 views
2

Я знаю, что этот вопрос задан много раз, но я не мог найти ответ, который работает на меня.Тупик при попытке вызова метода асинхронной синхронизации синхронно

Я пишу приложение 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() должен быть вызван в потоке пользовательского интерфейса, который мой метод обеспечивает.

Я уже пытался позвонить моему 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 !!! 

Я принял предложения, используя Nito.AsyncEx из this answer Стивена Клири на подобный вопрос.

Я также уже пытался добавить .ConfigureAwait(false) в await MainPage.DisplayAlert(...), но это также не сработало.

Когда я поставил точку останова на await MainPage.DisplayAlert линии, то он был поражен во всех, кроме двух последних вариантов, и когда я потом нажал F10, VS2015 остановил этот стек вызовов: enter image description here

Там не было исключением, хотя , Приложение просто зависает.

Кто-нибудь знает, как я могу назвать свой метод асинхронизации?

+0

Похоже, вы вызываете DisplayAlert внутри DisplayAlert так что вы будете просто продолжать называть это навсегда, следовательно, приложение висит –

+0

Выстрел в темноте, что может работать 'новый Handler(). Пост (новый Runnable (асинхронная() = > // code)); ' –

ответ

2

Возвращаемое значение OnJsConfirm указывает только, если вы будете обрабатывать диалог подтверждения. Поэтому вам нужно вернуть true, а остальные - асинхронно. И если возвращается ваш DisplayAlert, вы можете позвонить Confim() или Cancel() на JsResult в зависимости от результата задачи.

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; 
} 
Смежные вопросы