Xamarin重试失败的数据请求

时间:2017-07-25 07:33:31

标签: c# xamarin xamarin.ios xamarin.android task-parallel-library

Retry action Image

我正在构建一个Xamarin iOS& Android应用程序,我想对所有失败的webcall实现重试功能,或者在断开连接的情况下,我已经在BLL端使用Polly,我想让用户有可能手动重试,如所示以上图片

protected List<Task> _taskList;

_taskList.Add(Task.Run(async () =>
{
    try
    {
        **// Webservice Call**
        Task<UtilisateurDTO> utilisateurTask = UserFactory.Login(username, pwd,
            App.Hardware.GetDeviceId());

        UtilisateurDTO utilisateur = await utilisateurTask;

        if (utilisateur != null)
        {
            InvokeOnMainThread(() =>
            {
                **// Set result to ui component**
            });
        }
    }
    catch (Exception ex)
    {
        InvokeOnMainThread(() =>
        {
            // Add action button "Retry" to snackBar
            _snackBar = new TTGSnackbar("ex.Message", TTGSnackbarDuration.Forever, "Retry", (obj) => {
                // **Retry all tasks**
                Parallel.ForEach(_taskList, task => task.Start());
            });
            _snackBar.Show();
        });
    }
}));

我知道无法重试已完成的任务,我无法在任务之外调用我的Web服务(不阻止UI线程),那么替代方案是什么?

使用解决方案进行更新

如果你想在一个地方处理异常并重试,这是我的解决方案(不是最好的重新加载所有内容的原因)

// BaseViewClass

public abstract class BaseViewController:UIViewController
{

    // Function to override in child controllers
    protected abstract void ReloadData(TTGSnackbar obj);

    public void HandleExceptions(Exception e)
    {
        // On commence par cacher la ProgressBar
        InvokeOnMainThread(HideLoadigProgressBar);

        if (e is ConnectionLostException)
        {
            Console.WriteLine("ConnectionLostException: " + e.ToString());
            InvokeOnMainThread(() =>
            {
                _snackBar = new TTGSnackbar("Connection lost !", TTGSnackbarDuration.Forever, "retry", ReloadData);
                _snackBar.Show();
            });

        }
        else if (e is TimeoutException)
        {
            Console.WriteLine("TimeoutException: "+ e.ToString());
            InvokeOnMainThread(() =>
            {
                _snackBar = new TTGSnackbar("TimeoutException", TTGSnackbarDuration.Forever, "Retry", ReloadData);
                _snackBar.Show();
            });
        }
        .....................
}

// 其他ViewController

public partial class HomeController : BaseViewController
{
    public override void ViewDidLoad()
    {
        base.ViewDidLoad();
        LoadData();

    }

    public void LoadData(){
        Task.Run(async () =>
        {
            try
            {
                // Web calls
                Task<UtilisateurDTO> getUserTask = AccueilFactory.GetUser();

                UtilisateurDTO utilisateur = await getUserTask;

                // Set UI result
             }
             catch(Exception ex) {
                 HandleExceptions(ex);
             }
        }
   }

    protected override void ReloadData(TTGSnackbar obj)
    {
        LoadData();
    }
}

1 个答案:

答案 0 :(得分:0)

您必须在异常时再次调用您的函数,而不仅仅是重新运行上一个任务。

您的代码将是这样的:

private void Login() { try { LoginInner(); // here you call service and update UI } catch (Exception ex) { InvokeOnMainThread(() => { // Add action button "Retry" to snackBar _snackBar = new TTGSnackbar("ex.Message", TTGSnackbarDuration.Forever, "Retry", (obj) => { // **Retry all tasks** Parallel.ForEach(_taskList, LoginInner); // ** call again loginInner ** }); _snackBar.Show(); }); } }