Я использую Parse как хранилище данных для приложения, и я реализую их функциональность Facebook Login. AFAIK, этот метод входа не отличается от других методов async, поэтому, надеюсь, он применим.Отказ от асинхронного метода
Таким образом, есть страница Login.xaml, в которой есть кнопка «Войти в Facebook», и нажатие этой кнопки приведет вас к странице FacebookLogin.xaml, которая содержит только элемент управления WebBrowser
в соответствии с связанной документацией. В ContentPanel.Loaded
на FacebookLogin.xaml, я могу использовать следующий код войти в систему:
async void FacebookLogin()
{
try
{
user = await ParseFacebookUtils.LogInAsync(fbBrowser, new[] { "user_likes", "email" });
}
catch (OperationCanceledException oce)
{
// task was cancelled, try again
//task = null;
//FacebookLogin();
}
catch (Exception ex)
{
}
}
Если я на самом деле войти, он работает, и я могу перейти пользователя к следующей странице. Проблема происходит, когда я позволяю управление браузером нагрузка (поэтому метод async
является ждет), а затем нажмите Назад кнопку, , а затем вернуться к странице входа в Facebook снова.
Когда я это делаю, вызывается OperationCancelledException
, но я не уверен, как с этим справиться. То, что я пробовал:
В
catch
дляOperationCanceledException
, установить повторно инициализироватьWebBrowser
управление новым. Это не имело никакого эффекта.В том же
catch
, позвоните по телефонуFacebookLogin()
, чтобы повторить попытку. Это тоже не сработало.Я также пытался не использовать
await
и возвращатьTask<ParseUser>
, но я не был уверен, как это сделать.
Есть ли что-то я могу сделать, за исключением отмены, или использовать CancellationToken
, чтобы справиться с этим лучше? Я просто хочу правильно обработать отмену, чтобы я мог повторно загрузить страницу входа в систему Facebook, если пользователь нажимает «Назад».
РЕШЕНИЕ:
Хорошо, после того, как много указаний @JNYRanger, я пришел с рабочим раствором. Там может быть лучший способ, но это, похоже, работает. Вот весь код из моего FacebookLogin.xaml:
public partial class LoginFacebook : PhoneApplicationPage
{
Task<ParseUser> task;
CancellationTokenSource source;
public LoginFacebook()
{
InitializeComponent();
ContentPanel.Loaded += ContentPanel_Loaded;
}
async void ContentPanel_Loaded(object sender, RoutedEventArgs e)
{
try {
source = new CancellationTokenSource();
task = ParseFacebookUtils.LogInAsync(fbBrowser, new[] { "user_likes" }, source.Token);
await task;
// Logged in! Move on...
}
catch (Exception ex) { task = null; }
}
protected override void OnBackKeyPress(System.ComponentModel.CancelEventArgs e)
{
if (task != null) source.Cancel(false);
base.OnBackKeyPress(e);
}
}
Так в основном, когда «Back» нажата, я использую CancellationToken
, чтобы запросить отмены, который вызывает исключение. Когда возникает исключение, я установил task
в значение null. Теперь, когда вы переходите на страницу FacebookLogin (без предварительной регистрации), task
может быть успешно воссоздан.
Осторожно, у вас все еще есть методы async void, которые не являются обработчиками событий. – JNYRanger
Я не уверен, как заставить его работать без 'async void', потому что если' FacebookLogin() 'возвращает' Task', мне придется использовать 'await' на' FacebookLogin() ', что потребовало бы мне использовать 'async' в' ContentPanel_Loaded', что дает мне еще одну «асинхронную пустоту»? –
lhan
На самом деле, в соответствии с предоставленной вами статьей, если метод 'async' является обработчиком событий (поскольку' ContentPanel_Loaded' будет), это нормально. Так это было бы лучшим решением, чтобы просто сделать 'ContentPanel_Loaded'' async'? – lhan