如果发生异常,则取消多次等待的任务执行

问题描述 投票:0回答:1

上下文-问题在底部描述

因此,我们实现了从应用程序的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()被调用并导航,这不是我想要的!

但是,如果ExecuteTaskNavigationService.NavigateAsync任务抛出异常,它将停止执行,因此将不执行Login()

怎么了?非常感谢您的宝贵时间 !

c# xamarin xamarin.forms task-parallel-library
1个回答
0
投票
简短的回答是,TPL无法按照您描述的方式工作。如果Task2引发异常,则应该执行Task [

这可以在下面的示例代码中看到,它反映了您上面发布的结构:

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
© www.soinside.com 2019 - 2024. All rights reserved.