C# 关闭\销毁异步方法内的活动
在进行了大量搜索之后,我惊讶地发现没有任何关于销毁android活动的信息,而还有一项任务仍在等待:C# 关闭\销毁异步方法内的活动,c#,android,asynchronous,xamarin,xamarin.android,C#,Android,Asynchronous,Xamarin,Xamarin.android,在进行了大量搜索之后,我惊讶地发现没有任何关于销毁android活动的信息,而还有一项任务仍在等待: protected override void OnCreate(Bundle bundle) { base.OnCreate(bundle); SetContentView(Resource.Layout.Login); Button btnLogin = FindViewById<Button>(Resource.Id.bt
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
SetContentView(Resource.Layout.Login);
Button btnLogin = FindViewById<Button>(Resource.Id.btnLogin);
btnLogin.Click += async (sender, e) =>
{
await Authenticate();
};
}
private async Task Authenticate()
{
TextView txtUsername = FindViewById<TextView>(Resource.Id.txtUsername);
TextView txtPassword = FindViewById<TextView>(Resource.Id.txtPassword);
if (await Security.ProcessLogin(txtUsername.Text,txtPassword.Text))
{
StartActivity(typeof(actMaiMenu));
this.Finish();
}
else
{
\\Warn User
txtUsername.Text = "";
txtPassword.Text = "";
txtUsername.RequestFocus();
}
}
protectedoverride void OnCreate(捆绑包)
{
base.OnCreate(bundle);
SetContentView(Resource.Layout.Login);
按钮btnLogin=findviewbyd(Resource.Id.btnLogin);
btnLogin.Click+=async(发送方,e)=>
{
等待验证();
};
}
专用异步任务身份验证()
{
TextView txtUsername=FindViewById(Resource.Id.txtUsername);
TextView txtPassword=findviewbyd(Resource.Id.txtPassword);
if(等待Security.ProcessLogin(txtsername.Text、txtPassword.Text))
{
StartActivity(typeof(actMaiMenu));
这个;
}
其他的
{
\\警告用户
txtUsername.Text=“”;
txtPassword.Text=“”;
txtUsername.RequestFocus();
}
}
虽然在这种情况下有一个明显的解决办法,但我想知道这是否意味着什么。例如,任务持续在后台(或者更糟的是整个活动)
我没有收到任何错误,尽管点击事件在成功登录时没有收到完成状态。我不知道Xamarin,但是Android的
Asynctask
类始终绑定到活动,这意味着当活动被销毁时,它将停止
在这种情况下,我总是使用
服务
,而不是异步任务
我无法从文档中提供详细信息,但我发现(通过在带有调试的实际设备上运行这种类型的异步代码),恢复活动可以尝试恢复正在等待的任务。我最好的办法就是取消等待的任务
在我的类中,我有一个私有令牌和令牌源
private CancellationTokenSource cancelSource;
private CancellationToken cancelToken;
在OnResume和OnPause中取消任务
public override void OnResume ()
{
base.OnResume ();
if (cancelToken != null && cancelToken.CanBeCanceled && cancelSource != null) {
cancelSource.Cancel ();
}
}
public override void OnPause()
{
base.OnPause ();
if (cancelToken != null && cancelToken.CanBeCanceled && cancelSource != null) {
cancelSource.Cancel ();
}
}
我让异步方法将CancellationToken作为参数,并在调用站点中创建CancellationToken。因此,在您的代码中,我将执行以下操作:
btnLogin.Click += async (sender, e) =>
{
cancelSource = new CancellationTokenSource ();
cancelToken = cancelSource.Token;
this.Authenticate(cancelToken);
}
然后在异步函数中,在执行活动之前检查令牌的状态。大概是
private async Task Authenticate(CancellationToken cancellationToken)
{
....
bool loggedInOk= await Security.ProcessLogin(txtUsername.Text,txtPassword.Text);
if (cancellationToken.IsCancellationRequested)
{
// do something here as task was cancelled mid flight maybe just
return;
}
if (loggedInOk)
{
StartActivity(typeof(actMaiMenu));
this.Finish();
}
else
{
\\Warn User
txtUsername.Text = "";
txtPassword.Text = "";
txtUsername.RequestFocus();
}
}
您可能还需要考虑错误处理,如果Security.ProcessLogin()引发错误,会发生什么/应该发生什么。感谢Alex提供了如此详细的答案。如果身份验证任务继续,在您的情况下,您将捕获它并返回,这是绝对正确的。完全同意,如果任务即将陷入进一步的处理\tasks\whatever中,那么如果主任务已恢复,则立即退出主任务非常重要。但是,在这种情况下,我是否可以确认,如果确实发生了,它是否会在离开的.Finish()处重新启动,在任务完成后返回,并退出执行,准备再次单击按钮?我不确定我是否理解这个问题,但这是一个答案。如果在Security.ProcessLogin完成之前请求取消,那么接下来将发生的事情是该方法将返回(不调用任何其他内容)。在这一点上,该方法被发现正在执行,就像任何其他方法一样。如果恢复活动,然后再次单击btnLogin,则将调用整个身份验证方法(包括Security.ProcessLogin)。我并不是完全无视它,但在我的“简单”例子中,如果有一份简历,而且我没有修改我的代码,那么它不会就此结束吗?@AlexC为什么在OnResume中取消?在调用cancelSource.Cancel()之前,您也不需要检查cancelToken,类似于:
if(cancelSource!=null){cancelSource.Cancel();cancelSource=null;}
应该可以做到这一点。