因此,我们实现了从应用程序的Tasks
中执行BaseViewModel
的流程,以避免在我们的[[ C0]。
基本上,我们在try catch
中对这样的命令执行任务:
ViewModels's Commands
ViewModel
中的 LoginCommand = new DelegateCommand(async () => await ExecuteTask(Login()));
方法:
ExecuteTask
[我们传递给ViewModelBase
的 protected async Task ExecuteTask(Task task)
{
IsBusy = true;
try
{
await task;
}
catch (WebException ex)
{
UserDialogsService.ShowError(Connectivity.NetworkAccess != NetworkAccess.Internet
? AppResources.NoNetworkErrorText
: AppResources.GenericErrorText);
}
catch (ApiException ex)
{
var apiError = await ex.GetContentAsAsync<ApiError>();
UserDialogsService.ShowError(Connectivity.NetworkAccess != NetworkAccess.Internet
? AppResources.NoNetworkErrorText
: apiError.UserMessage);
}
catch (TaskCanceledException ex)
{
UserDialogsService.ShowError(Connectivity.NetworkAccess != NetworkAccess.Internet
? AppResources.NoNetworkErrorText
: AppResources.GenericErrorText);
}
catch (HttpRequestException ex)
{
UserDialogsService.ShowError(Connectivity.NetworkAccess != NetworkAccess.Internet
? AppResources.NoNetworkErrorText
: AppResources.GenericErrorText);
}
finally
{
IsBusy = false;
}
}
任务:
Login
ExecuteTask
中的private async Task Login()
{
await _authenticationService.Login(new UserLoginDto { UserName = User.Email, Password = User.PlainPassword });
await NavigationService.NavigateAsync("/MainTabbedPage?createTab=CustomNavigationPage|MainPage&" +
"createTab=CustomNavigationPage|Page1&" +
"createTab=CustomNavigationPage|Page2");
}
任务:
Login
AuthenticationService
方法:
public async Task Login(UserLoginDto userLoginDto)
{
var cts = new CancellationTokenSource();
var task = _apiManager.RemoteRequestAsync(_authEndpoints.GetApi(Priority.UserInitiated)
.Login(userLoginDto, cts.Token));
_apiManager.RunningTasks.Add(task.Id, cts);
var user = await task;
await ProcessPostLogin(user, cts);
}
void方法ProcessPostLogin
,基本上保留了一些偏好:
public async Task ProcessPostLogin(User user, CancellationTokenSource cts)
{
await SaveCredentials(user.AccessToken);
var task = _userEndPoints.GetApi(Priority.Background).PostUserInfos(
user.Id,
new UserInformations
{
AppCenterId = _preferencesService.GetPreference(GlobalSetting.UserPreferences.AppInstallId)
},
cts.Token);
_apiManager.RunningTasks.Add(task.Id, cts);
await task;
SaveUserPreferences(user);
}
[如果出于任何原因,SaveUserPreferences
抛出异常,例如BadRequest或其他任何东西,我都希望调用者方法,因此将 private void SaveUserPreferences(User user)
{
_preferencesService.SavePreference(user.Id.ToString(), GlobalSetting.UserPreferences.UserId);
_preferencesService.SavePreference(user.Provider.ToString(), GlobalSetting.UserPreferences.UserProvider);
_preferencesService.SavePreference(string.Join(",", user.Roles), GlobalSetting.UserPreferences.UserRoles);
}
传递给ProcessPostLogin
以停止其执行。但是,事实并非如此,Login()
被调用并导航,这不是我想要的!
但是,如果ExecuteTask
的NavigationService.NavigateAsync
任务抛出异常,它将停止执行,因此将不执行Login()
。
怎么了?非常感谢您的宝贵时间 !
这可以在下面的示例代码中看到,它反映了您上面发布的结构:
AuthenticationService
您将获得以下输出:
ProcessPostLogin
要确认的一件事-async Task Main()
{
try
{
await Task1();
await Task2();
await Task3();
}
catch(Exception e)
{
Console.WriteLine(e.Message);
}
}
// Define other methods, classes and namespaces here
public async Task<string> Task1()
{
Console.WriteLine("Starting task 1");
await Task.Delay(1);
return "Task 1 succeeded";
}
public async Task Task2()
{
Console.WriteLine("Starting task 2");
await Task.FromException(new Exception("Task 2 failed"));
}
public async Task Task3()
{
Console.WriteLine("Starting task 3");
await Task.Delay(1);
}
返回Starting task 1
Starting task 2
Task 2 failed
还是ProcessPostLogin
?异步方法(一般而言)应该
never返回
Task
。