处理异步方法取消 [英] Handle cancellation of async method

查看:211
本文介绍了处理异步方法取消的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用解析作为一个应用程序的数据存储,而我自己实施的 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:


  1. OperationCanceledException ,设置重新初始化 web浏览器控制到一个新的。这是没有效果的。

  1. In the catch for the OperationCanceledException, set re-initialize the WebBrowser 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆