任务完成后没有继续
task oncomplete is not moving on
我需要在任务完成时转到下一个 activity,但它不会。它成功地在数据库中创建了一个帐户,但不会继续。
如下所示,我尝试了 oncomplete(task) 但是一旦我输入凭据并点击注册,它就会创建帐户但不会继续。
下面的代码(对 Http 请求使用 refit):
using Kula.API;
using Refit;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xamarin.Forms;
namespace Kula
{
// Learn more about making custom code visible in the Xamarin.Forms previewer
// by visiting https://aka.ms/xamarinforms-previewer
[DesignTimeVisible(false)]
public partial class MainPage : ContentPage
{
// set variables
Entry RinputEmail;
Entry RinputPassword;
Entry RinputUsername;
Entry RinputFullName;
IMyAPI myAPI;
APIRequestHelper apiRequestHelper;
public MainPage()
{
InitializeComponent();
myAPI = RestService.For<IMyAPI>("http://10.0.2.2:8080");
apiRequestHelper = new APIRequestHelper(myAPI);
// reference mainpage.xamal
RinputEmail = this.FindByName<Entry>("Remail");
RinputPassword = this.FindByName<Entry>("Rpassword");
RinputUsername = this.FindByName<Entry>("Rusername");
RinputFullName = this.FindByName<Entry>("Rfullname");
}
async private void GTLogin_Clicked(object sender, EventArgs e)
{
//navigate to Login page
await Navigation.PushAsync(new Login());
}
async private void registerUser_Clicked(object sender, EventArgs e)
{
await apiRequestHelper.RequestRegisterUserAsync((RinputEmail.Text).ToString(),
(RinputPassword.Text).ToString(), (RinputUsername.Text).ToString(),
(RinputFullName.Text).ToString()).ContinueWith((nextpage) => { Navigation.PushAsync(new
Login()); });
}
}
};
API_REQUEST_HELPER
namespace Kula.API
{
public class APIRequestHelper
{
IMyAPI myAPI;
public APIRequestHelper(IMyAPI myAPI)
{
this.myAPI = myAPI;
}
public async Task RequestRegisterUserAsync(string email, string
password, string username, string fullname)
{
//create params for request
Dictionary<string, object> data = new Dictionary<string,
object>();
data.Add("username", username);
data.Add("email", email);
data.Add("password", password);
data.Add("fullname", fullname);
await myAPI.RegisterUser(data);
}
/*
public async Task RequestRegisterUserAsync(string email, string
password, Boolean returntoken)
{
//create params for request
Dictionary<string, object> data = new Dictionary<string,
object>();
data.Add("email", email);
data.Add("password", password);
data.Add("returnSecureToken", returntoken);
string result = await myAPI.RegisterUsertwo(data);
}
*/
public async Task RequestLoginUserAsync(string email, string
password, Boolean returntoken)
{
//create params for request
Dictionary<string, object> data = new Dictionary<string,
object>();
data.Add("email", email);
data.Add("password", password);
data.Add("returnSecureToken", returntoken);
string result = await myAPI.LoginUser(data);
}
public async Task RequestLoginUserAsync(string email, string password)
{
//create params for request
Dictionary<string, object> data = new Dictionary<string,
object>();
data.Add("email", email);
data.Add("password", password);
string result = await myAPI.LoginUser(data);
}
public async Task RequestSaveProfileInfoAsync(string username, string fullname)
{
//create params for request
Dictionary<string, object> data = new Dictionary<string,
object>();
data.Add("username", username);
data.Add("fullname", fullname);
string result = await myAPI.SaveProfileInfo(data);
}
}
}
MY_API
using Kula.Models;
using Refit;
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
namespace Kula.API
{
public interface IMyAPI
{
[Get("/Getuid")]
Task<string> GetUid();
[Post("/register")]
Task<string>
RegisterUser([Body(BodySerializationMethod.UrlEncoded)]
Dictionary<string, object> data);
[Get("/response")]
Task<string> GetResponse();
[Post("/accounts:signInWithPassword?key=")]
Task<string> LoginUser([Body(BodySerializationMethod.UrlEncoded)]
Dictionary<string, object> data);
[Post("/SaveProfileInfo")]
Task<string>
SaveProfileInfo([Body(BodySerializationMethod.UrlEncoded)]
Dictionary<string, object> data);
[Get("/GetProfileInfo")]
Task<List<string>> GetProfileInfo();
[Get("/GetSocialFeedTiles")]
Task<List<string>> GetSocialFeedTiles();
}
因为 apiRequestHelper
或您的方法 RequestRegisterUserAsync
返回的内容无法获得 Main UI 的句柄,因此您必须使用委托来完成它。
await apiRequestHelper.RequestRegisterUserAsync((RinputEmail.Text).ToString(),
(RinputPassword.Text).ToString(), (RinputUsername.Text).ToString(),
(RinputFullName.Text).ToString()).ContinueWith(delegate { Navigation.PushAsync(new
Login()); });
或者您可以按照上面的答案将代码分开。
await apiRequestHelper.RequestRegisterUserAsync((RinputEmail.Text).ToString(),(RinputPassword.Text).ToString(),(RinputUsername.Text).ToString(),(RinputFullName.Text).ToString());
await Navigation.PushAsync(new Login());
我用下面的简单代码模拟了你的问题:
async private void registerUser_Clicked(object sender, EventArgs e)
{
await Task.Delay(5000).ContinueWith((x) => Navigation.PushAsync(new Page1()));
}
如果您在 Navigation.PushAsync
行中放置一个断点,您会注意到它是从一个非 主线程 的线程调用的。这就是为什么即使代码到达该部分,它也没有效果:您只能从 Main Thread!
更改 UI
要实现这一点,您可以简单地以常规方式使用 async await,如下所示:
async private void registerUser_Clicked(object sender, EventArgs e)
{
await Task.Delay(5000);
await Navigation.PushAsync(new Page1());
}
或者回到你自己的代码:
async private void registerUser_Clicked(object sender, EventArgs e)
{
await apiRequestHelper.RequestRegisterUserAsync((RinputEmail.Text).ToString(),(RinputPassword.Text).ToString(), (RinputUsername.Text).ToString(),(RinputFullName.Text).ToString());
await Navigation.PushAsync(new Login());
}
有关 async/await + Xamarin.Forms 的精彩 post 可以在这里找到:
https://devblogs.microsoft.com/xamarin/getting-started-with-async-await/
奖金:
您提到使用 OnComplete
:使用它来让您的 EventHandler 启动 Login 页面的方法是通过使用 ConfigureAwait
:
将任务配置为 return 到主线程
Task.Delay(5000).ConfigureAwait(true).GetAwaiter().OnCompleted(()=>Navigation.PushAsync(new Page1()));
注意 ConfigureAwait(true) 的使用,如果改用 ConfigureAwait(false) 则 PushAsync
方法再次从主线程以外的线程调用!
如下所示,我尝试了 oncomplete(task) 但是一旦我输入凭据并点击注册,它就会创建帐户但不会继续。
下面的代码(对 Http 请求使用 refit):
using Kula.API;
using Refit;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xamarin.Forms;
namespace Kula
{
// Learn more about making custom code visible in the Xamarin.Forms previewer
// by visiting https://aka.ms/xamarinforms-previewer
[DesignTimeVisible(false)]
public partial class MainPage : ContentPage
{
// set variables
Entry RinputEmail;
Entry RinputPassword;
Entry RinputUsername;
Entry RinputFullName;
IMyAPI myAPI;
APIRequestHelper apiRequestHelper;
public MainPage()
{
InitializeComponent();
myAPI = RestService.For<IMyAPI>("http://10.0.2.2:8080");
apiRequestHelper = new APIRequestHelper(myAPI);
// reference mainpage.xamal
RinputEmail = this.FindByName<Entry>("Remail");
RinputPassword = this.FindByName<Entry>("Rpassword");
RinputUsername = this.FindByName<Entry>("Rusername");
RinputFullName = this.FindByName<Entry>("Rfullname");
}
async private void GTLogin_Clicked(object sender, EventArgs e)
{
//navigate to Login page
await Navigation.PushAsync(new Login());
}
async private void registerUser_Clicked(object sender, EventArgs e)
{
await apiRequestHelper.RequestRegisterUserAsync((RinputEmail.Text).ToString(),
(RinputPassword.Text).ToString(), (RinputUsername.Text).ToString(),
(RinputFullName.Text).ToString()).ContinueWith((nextpage) => { Navigation.PushAsync(new
Login()); });
}
}
};
API_REQUEST_HELPER
namespace Kula.API
{
public class APIRequestHelper
{
IMyAPI myAPI;
public APIRequestHelper(IMyAPI myAPI)
{
this.myAPI = myAPI;
}
public async Task RequestRegisterUserAsync(string email, string
password, string username, string fullname)
{
//create params for request
Dictionary<string, object> data = new Dictionary<string,
object>();
data.Add("username", username);
data.Add("email", email);
data.Add("password", password);
data.Add("fullname", fullname);
await myAPI.RegisterUser(data);
}
/*
public async Task RequestRegisterUserAsync(string email, string
password, Boolean returntoken)
{
//create params for request
Dictionary<string, object> data = new Dictionary<string,
object>();
data.Add("email", email);
data.Add("password", password);
data.Add("returnSecureToken", returntoken);
string result = await myAPI.RegisterUsertwo(data);
}
*/
public async Task RequestLoginUserAsync(string email, string
password, Boolean returntoken)
{
//create params for request
Dictionary<string, object> data = new Dictionary<string,
object>();
data.Add("email", email);
data.Add("password", password);
data.Add("returnSecureToken", returntoken);
string result = await myAPI.LoginUser(data);
}
public async Task RequestLoginUserAsync(string email, string password)
{
//create params for request
Dictionary<string, object> data = new Dictionary<string,
object>();
data.Add("email", email);
data.Add("password", password);
string result = await myAPI.LoginUser(data);
}
public async Task RequestSaveProfileInfoAsync(string username, string fullname)
{
//create params for request
Dictionary<string, object> data = new Dictionary<string,
object>();
data.Add("username", username);
data.Add("fullname", fullname);
string result = await myAPI.SaveProfileInfo(data);
}
}
}
MY_API
using Kula.Models;
using Refit;
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
namespace Kula.API
{
public interface IMyAPI
{
[Get("/Getuid")]
Task<string> GetUid();
[Post("/register")]
Task<string>
RegisterUser([Body(BodySerializationMethod.UrlEncoded)]
Dictionary<string, object> data);
[Get("/response")]
Task<string> GetResponse();
[Post("/accounts:signInWithPassword?key=")]
Task<string> LoginUser([Body(BodySerializationMethod.UrlEncoded)]
Dictionary<string, object> data);
[Post("/SaveProfileInfo")]
Task<string>
SaveProfileInfo([Body(BodySerializationMethod.UrlEncoded)]
Dictionary<string, object> data);
[Get("/GetProfileInfo")]
Task<List<string>> GetProfileInfo();
[Get("/GetSocialFeedTiles")]
Task<List<string>> GetSocialFeedTiles();
}
因为 apiRequestHelper
或您的方法 RequestRegisterUserAsync
返回的内容无法获得 Main UI 的句柄,因此您必须使用委托来完成它。
await apiRequestHelper.RequestRegisterUserAsync((RinputEmail.Text).ToString(),
(RinputPassword.Text).ToString(), (RinputUsername.Text).ToString(),
(RinputFullName.Text).ToString()).ContinueWith(delegate { Navigation.PushAsync(new
Login()); });
或者您可以按照上面的答案将代码分开。
await apiRequestHelper.RequestRegisterUserAsync((RinputEmail.Text).ToString(),(RinputPassword.Text).ToString(),(RinputUsername.Text).ToString(),(RinputFullName.Text).ToString());
await Navigation.PushAsync(new Login());
我用下面的简单代码模拟了你的问题:
async private void registerUser_Clicked(object sender, EventArgs e)
{
await Task.Delay(5000).ContinueWith((x) => Navigation.PushAsync(new Page1()));
}
如果您在 Navigation.PushAsync
行中放置一个断点,您会注意到它是从一个非 主线程 的线程调用的。这就是为什么即使代码到达该部分,它也没有效果:您只能从 Main Thread!
要实现这一点,您可以简单地以常规方式使用 async await,如下所示:
async private void registerUser_Clicked(object sender, EventArgs e)
{
await Task.Delay(5000);
await Navigation.PushAsync(new Page1());
}
或者回到你自己的代码:
async private void registerUser_Clicked(object sender, EventArgs e)
{
await apiRequestHelper.RequestRegisterUserAsync((RinputEmail.Text).ToString(),(RinputPassword.Text).ToString(), (RinputUsername.Text).ToString(),(RinputFullName.Text).ToString());
await Navigation.PushAsync(new Login());
}
有关 async/await + Xamarin.Forms 的精彩 post 可以在这里找到:
https://devblogs.microsoft.com/xamarin/getting-started-with-async-await/
奖金:
您提到使用 OnComplete
:使用它来让您的 EventHandler 启动 Login 页面的方法是通过使用 ConfigureAwait
:
Task.Delay(5000).ConfigureAwait(true).GetAwaiter().OnCompleted(()=>Navigation.PushAsync(new Page1()));
注意 ConfigureAwait(true) 的使用,如果改用 ConfigureAwait(false) 则 PushAsync
方法再次从主线程以外的线程调用!