C # Polar asynchronous wait: Wait for user confirmation to repeat

I am creating a Xamarin.Forms application for iOS and Android, where I store data and a local sqlite and online database on an Azure server. Although my application requires an Internet connection, which it always checks with the plug-in, I found that sometimes I get an exception if the user loses the average cellular network reception request.

I want to have a method that I can call all my server requests to retry the request if an error occurs. I would also like to ask the user to enter it before retrying. The stream will look like this:

Server call -> Exception Caught -> Ask the user if they want to try again -> Retry

I found a Polly package that is configured to handle try / catch attempts in C #. I currently have this code setting:

public class WebExceptionCatcher<T, R> where T : Task<R>
{      
    public async Task<R> runTask(Func<T> myTask)
    {
        Policy p = Policy.Handle<WebException>()
        .Or<MobileServiceInvalidOperationException>()
        .Or<HttpRequestException>()
        .RetryForeverAsync(onRetryAsync: async (e,i) => await RefreshAuthorization());

        return await p.ExecuteAsync<R>(myTask);
    }
}

My method RefreshAuthorization()simply displays DisplayAlerton the current page of the main thread:

private async Task RefreshAuthorization()
{
    bool loop = true;
    Device.BeginInvokeOnMainThread(async () =>
    {
        await DisplayAlert("Connection Lost", "Please re-connect to the internet and try again", "Retry");
        loop = false;
    });

    while (loop)
    {
        await Task.Delay(100); 
    }
}

When I debug this and disconnect my internet connection. DisplayAlertnever displayed. One of two things:

  • Execution keeps repeating my task over and over without doing
  • A System.AggregateExceptionis displayed with the following message:

System.AggregateException: A Task exception(s) were not observed either by Waiting on the Task or accessing its Exception property. As a result, the unobserved exception was rethrown by the finalizer thread. ---> System.Net.Http.HttpRequestException: An error occurred while sending the request

Does anyone know how to successfully pause execution when a task fails and wait for the user to resume work?

UPDATE:

After entering the call DisplayAlertinside the method, Device.BeginInvokeOnMainThreadI found a way around AggregateException. However, now I have a different problem.

, DisplayAlert, . , , onRetry, RetryForeverAsync . , , , , , . , , , . , RetryForeverAsync .

runTask():

Task<TodoItem> t = App.MobileService.GetTable<TodoItem>().LookupAsync(id);
WebExceptionCatcher<Task<TodoItem>, TodoItem> catcher = new WebExceptionCatcher<Task<TodoItem>, TodoItem>();

runTask, :

TodoItem item = await catcher.runTask(() => t);

TodoItem item = await catcher.runTask(async () => await t);
0
1

.RetryForeverAsync(...) . , , onRetryAsync:. :

.RetryForeverAsync(onRetryAsync: async (e,i) => await RefreshAuthorization());


, : , onRetry:, , onRetry ( void), async .

, async-delegate-assign-to-sync-param async void; / . async void , .

System.AggregateException: A Task exception(s) were not observed myTask ( q ).

:

Re:

, RetryForeverAsync .

( / ), , , Func<Task<R>> , - Func<Task<R>> . . : retry.

- (, ) , , RefreshAuthorization() , , .

public class WebExceptionCatcher<T, R> where T : Task<R>
{      
    public async Task<R> runTask(Func<T> t)
    {
        int j = 0;
        Policy p = Policy.Handle<WebException>()
        .Or<MobileServiceInvalidOperationException>()
        .Or<HttpRequestException>()
        .RetryForeverAsync(onRetryAsync: async (e,i) => await RefreshAuthorization());

        return await p.ExecuteAsync<R>( async () => 
        {
            j++;
            if ((j % 5) == 0) Device.BeginInvokeOnMainThread(async () =>
            {
                 await DisplayAlert("Making retry "+ i, "whatever", "Ok");
            });
            await myTask;
        });
    }
}

RefreshAuthorization()) , Connection Lost , Making retry 5.

RefreshAuthorization()) , ( ) , Connection Lost. , Connection Lost , Making retry 5, Making retry 10 ( .., , ), Connection Lost.

(, ) , , Polly . myTask, myTask - .


UPDATE : " runTask():"

: , , , .

:

Task<TodoItem> t = App.MobileService.GetTable<TodoItem>().LookupAsync(id);
TodoItem item = await catcher.runTask(() => t); // Or same effect: TodoItem item = await catcher.runTask(async () => await t);

- App.MobileService.GetTable<TodoItem>().LookupAsync(id) , Polly ( , while for ).

A Task "re-runnable": Task . :

Task<TodoItem> t = App.MobileService.GetTable<TodoItem>().LookupAsync(id);

LookupAsync(id) t a Task, , LookupAsync ( ) . lambda () => t, Task, . ( t , , func , - LookupAsync(id).). , , , , , Polly, await -ing a Task, , .

Task , , :

int i = 0;
int j = i++;
Func<int> myFunc = () => j;
for (k=0; k<5; k++) Console.Write(myFunc());

, 12345, (, , j ) 11111.

, :

TodoItem item = await catcher.runTask(() => App.MobileService.GetTable<TodoItem>().LookupAsync(id));

lambda .LookupAsync(id) , Task<ToDoItem>, .

0

Source: https://habr.com/ru/post/1687631/


All Articles