title: Handle cancellation of async method
body: <p>I'm using <a href="http://www.parse.com" rel="nofollow">Parse</a> as a data store for an app, and I am implementing their <a href="https://parse.com/docs/dotnet_guide#fbusers-signup" rel="nofollow">Facebook Login</a> functionality. AFAIK, this Login method isn't any different than other async methods so hopefully it applies. </p>
  
  <p>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 <code>WebBrowser</code> control as per the linked Parse documenation. In <code>ContentPanel.Loaded</code> on FacebookLogin.xaml, I can use the following code to log in: </p>
  
  <pre><code>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)
     {
     }
  }
  </code></pre>
  
  <p>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 <code>async</code> method is <em>waiting</em>), and then hit the <strong>Back</strong> button, <strong>and then come back to the Facebook Login page again</strong>. </p>
  
  <p>When I do this, an <code>OperationCancelledException</code> is thrown, but I'm not sure how to handle it. What I've tried:</p>
  
  <ol>
  <li><p>In the <code>catch</code> for the <code>OperationCanceledException</code>, set re-initialize the <code>WebBrowser</code> control to a new one. This had no effect.</p></li>
  <li><p>In the same <code>catch</code>, call <code>FacebookLogin()</code> again, to retry. This also didn't work. </p></li>
  <li><p>I've also tried not using <code>await</code> and returning a <code>Task&lt;ParseUser&gt;</code> but I wasn't sure how to go about doing that either.</p></li>
  </ol>
  
  <p>Is there something I can do with the cancellation exception, or use a <code>CancellationToken</code> 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".</p>
  
  <p><strong>SOLUTION:</strong></p>
  
  <p>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:</p>
  
  <pre><code>public partial class LoginFacebook : PhoneApplicationPage
  {
     Task&lt;ParseUser&gt; 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);
     }
  }
  </code></pre>
  
  <p>So basically, when "Back" is pressed, I use the <code>CancellationToken</code> to request a cancel, which throws an exception. When the exception occurs, I set <code>task</code> to null. Now, when re-navigating to the FacebookLogin page (without previously logging in), the <code>task</code> can be successfully recreated. </p>