C# 异步方法的句柄取消
我将其用作应用程序的数据存储,并实现其功能。好吧,这个登录方法和其他异步方法没有什么不同,所以希望它能应用 因此,有一个Login.xaml页面,其中有一个“使用Facebook登录”按钮,点击该按钮将进入FacebookLogin.xaml页面,该页面仅包含链接解析文档中的C# 异步方法的句柄取消,c#,asynchronous,windows-phone-8,async-await,cancellationtokensource,C#,Asynchronous,Windows Phone 8,Async Await,Cancellationtokensource,我将其用作应用程序的数据存储,并实现其功能。好吧,这个登录方法和其他异步方法没有什么不同,所以希望它能应用 因此,有一个Login.xaml页面,其中有一个“使用Facebook登录”按钮,点击该按钮将进入FacebookLogin.xaml页面,该页面仅包含链接解析文档中的WebBrowser控件。在FacebookLogin.xaml上的ContentPanel.Loaded中,我可以使用以下代码登录: async void FacebookLogin() { try {
WebBrowser
控件。在FacebookLogin.xaml上的ContentPanel.Loaded
中,我可以使用以下代码登录:
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
方法正在等待),然后点击Back按钮,然后再次返回Facebook登录页面时,就会出现问题
当我执行此操作时,会抛出一个操作取消异常
,但我不确定如何处理它。我所尝试的:
操作取消例外
的捕获
中,将WebBrowser
控件重新初始化为新控件。这没有效果catch
中,再次调用FacebookLogin()
,以重试。这也没用await
并返回任务
,但我也不知道该怎么做CancellationToken
更好地处理这个问题吗?我只是想妥善处理取消,以便在用户按“后退”时可以重新加载Facebook登录页面
解决方案:
好的,在@JNYRanger的大量指导下,我想出了一个有效的解决方案。也许有更好的办法,但这似乎有效。以下是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);
}
}
公共部分类LoginFacebook:PhoneApplicationPage
{
任务;
取消令牌源;
公共登录facebook()
{
初始化组件();
ContentPanel.Loaded+=ContentPanel\u Loaded;
}
已加载异步void ContentPanel_(对象发送方,路由目标)
{
试一试{
source=新的CancellationTokenSource();
task=ParseFacebookUtils.LogInAsync(fbBrowser,new[]{“user_likes”},source.Token);
等待任务;
//已登录!继续。。。
}
catch(异常ex){task=null;}
}
BackKeyPress上受保护的覆盖无效(System.ComponentModel.CancelEventArgs e)
{
if(task!=null)source.Cancel(false);
基础。按Backkeypress(e);
}
}
所以基本上,当按下“Back”时,我使用
CancellationToken
请求取消,这会引发异常。当异常发生时,我将task
设置为null。现在,当重新导航到FacebookLogin页面(之前未登录)时,可以成功地重新创建任务 从来没有异步void
方法。您无法正确处理其中的异常。如果async
方法不返回任何内容,请使用async Task
(非泛型)作为返回类型
然后,您可以等待返回的任务
正确处理异常
如果要设置useCancellationTokens
使您可以将CancellationTokenSource
的令牌传递给async
方法。然后,您可以将该令牌注册到回调中,或者继续将该令牌传递到LoginAsync
方法中(如果该重载可用)。我用这个来熟悉取消的方法
另请参阅MSDN博客中有关避免async void
问题的这篇文章:
编辑
根据你问题中的编辑,我想指出一些东西。如果您致电
Task<ParseUser> t = FacebookLogin()
由于这是在一个事件处理程序(已加载)中,因此可以使用异步void
至于取消时会发生什么,这取决于你。您可以关闭登录窗口,取消其他任务/方法等。谢谢您提供的信息,请查看我的更新。我仍然很困惑,当发生取消异常时,我到底需要做什么?这取决于当方法被取消时您希望发生什么。当方法被取消时,您希望发生什么?还请记住,当您调用wait
时,您得到的是包装的值,而不是任务本身。对,我不需要任务,只需要ParseUser
,这样我就可以在以后使用它。因此,当我转到FacebookLogin.xaml时,浏览器将加载,异步方法将等待用户登录。如果用户没有登录,而是点击“返回”,然后再次返回FacebookLogin.xaml页面,则会发生取消异常。我不需要任何特别的事情发生,我只需要正确地处理任务,这样我就可以再次尝试调用LoginAsync()
。这就是我感到困惑的地方。我可以捕获异常,但是如果我尝试从那里再次调用FacebookLogin()
,我会立即收到另一个任务取消异常。好像页面或其他东西需要刷新。这可能是另一个问题。但是,最好在此时取消整个登录并更改窗口,而不是自动重试。请小心,您仍然有不是事件处理程序的async void
方法。我不确定如何在没有async void
的情况下使其工作,因为如果FacebookLogin()
返回一个任务
,我必须在FacebookLogin()
上使用wait
,这将要求我在ContentPanel\u加载的上使用async
,这会给我另一个async void
?实际上,根据您提供的文章,如果async
m
ParseUser p = await FacebookLogin();