处理异步方法取消 [英] Handle cancellation of async method
问题描述
我使用解析作为一个应用程序的数据存储,而我自己实施的 Facebook的登录功能。据我所知,这种登录方式是不是比其他的异步方法,所以希望它适用于任何不同。
I'm using Parse as a data store for an app, and I am implementing their Facebook Login functionality. AFAIK, this Login method isn't any different than other async methods so hopefully it applies.
因此,有一个Login.xaml页面,即有与Facebook登录按钮,并轻敲这个按钮将包含FacebookLogin.xaml页面只有 web浏览器
控制按链接解析documenation。在 ContentPanel.Loaded
上FacebookLogin.xaml,我可以使用下面的code登录:
So there is a Login.xaml page, that has a button for "Login with Facebook", and tapping this button takes you to the FacebookLogin.xaml page which contains only the WebBrowser
control as per the linked Parse documenation. In ContentPanel.Loaded
on FacebookLogin.xaml, I can use the following code to log in:
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)
{
}
}
如果我实际登录,它的工作原理,我可以将用户导航到下一个页面。在问题发生时,我让浏览器控制负载(因此异步
方法的等的),然后按返回按钮,,然后再回到Facebook的登录页面再次。
If I actually log in, it works, and I can navigate the user to the next page. The problem happens when I let the browser control load (so the async
method is waiting), and then hit the Back button, and then come back to the Facebook Login page again.
当我这样做,一个 OperationCancelledException
被抛出,但我不知道如何处理它。我已经试过:
When I do this, an OperationCancelledException
is thrown, but I'm not sure how to handle it. What I've tried:
-
在
抓
为OperationCanceledException
,设置重新初始化web浏览器
控制到一个新的。这是没有效果的。
In the
catch
for theOperationCanceledException
, set re-initialize theWebBrowser
control to a new one. This had no effect.
在同一个抓
,电话 FacebookLogin()
再次重试。这也没有工作。
In the same catch
, call FacebookLogin()
again, to retry. This also didn't work.
我也尝试不使用伺机
并返回任务< ParseUser>
,但我没'T知道如何去这样做,要么。
I've also tried not using await
and returning a Task<ParseUser>
but I wasn't sure how to go about doing that either.
有什么我可以取消除做,或者使用的CancellationToken
来处理这更好的?我只是想妥善处理被取消,这样我就可以重新加载的Facebook的登录页面,如果用户presses后退。
Is there something I can do with the cancellation exception, or use a CancellationToken
to handle this better? I just want to properly handle the cancellation so that I can re-load the Facebook Login page if the user presses "Back".
解决方案:
好吧,从@JNYRanger太多指导后,我想出了一个可行的解决方案。有可能是一个更好的办法,但是这似乎工作。下面是从我的FacebookLogin.xaml整个code:
Ok, after much guidance from @JNYRanger, I have come up with a working solution. There may be a better way, but this seems to work. Here is the entire code from my 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);
}
}
所以基本上,当后退是pressed,我使用的CancellationToken
来要求取消,这将引发异常。当异常发生时,我设置任务
为null。现在,当再导航到FacebookLogin页面(不pviously登录$ P $),在任务
可以成功地重新创建。
So basically, when "Back" is pressed, I use the CancellationToken
to request a cancel, which throws an exception. When the exception occurs, I set task
to null. Now, when re-navigating to the FacebookLogin page (without previously logging in), the task
can be successfully recreated.
推荐答案
从来没有异步无效
方法。你不能处理异常正常在其中。如果你的异步
方法不返回任何使用异步任务
(不通用)作为返回类型来代替。
Never have async void
methods. You cannot handle exceptions properly in them. If your async
method does not return anything use async Task
(not generic) as the return type instead.
然后,您可以在等待你回来工作
来妥善处理的异常。
You can then await on your returned Task
to handle the exceptions properly.
如果你要设置使用 CancellationTokens
让你你通过 CancellationTokenSource
的标记到异步
方法。然后,您可以注册这个道理无论是回调还是继续令牌传递到 LoginAsync
方法,如果是超载是可用的。我用这个 MSDN文章得到我自己熟悉的取消方法。
If you are going to set use CancellationTokens
make your you pass your CancellationTokenSource
's token to the async
method. You can then register this token either to a callback or continue to pass the token into the LoginAsync
method if that overload is available. I used this MSDN article to get myself familiar with the cancellation methods.
另外看看这篇文章从MSDN博客中关于避免异步无效
问题:的异步等待最佳实践
Also take a look at this article from the MSDN blog in regards to avoiding the async void
issues: Async-Await Best Practices
修改结果
每在你的问题编辑我想点东西出来。如果你调用结果
EDIT
Per the edit in your question I wanted to point something out. If you call
Task<ParseUser> t = FacebookLogin()
您现在有一个工作
的对象,你可以做的东西用。但是,如果你只是想在 ParseUser
对象,并没有延续或需要做别的用工作
你应该使用等待
再次
You now have a Task
object that you can do stuff with. However, if you just want the ParseUser
object and have no continuations or need to do anything else with the Task
you should use await
once again.
ParseUser p = await FacebookLogin();
由于这是一个事件处理程序(加载)是一个例外,它的确定有一个异步无效
至于什么时候取消会出现什么情况,以及这是给你的。您可以关闭登录窗口,取消其他任务/方法,等等。
As to what happens when you a cancellation occurs, well that's up to you. You can close the login window, cancel other tasks/methods, etc.
这篇关于处理异步方法取消的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!