Как установить тайм-аут в библиотеке Refit

Я использую библиотеку Refit в своем приложении Xamarin, я хочу установить тайм-аут на 10 секунд для запроса. Есть ли способ сделать это в ремонт?

Интерфейс:

interface IDevice
{
  [Get("/app/device/{id}")]
  Task<Device> GetDevice(string id, [Header("Authorization")] string authorization);
}

Вызов API

var device = RestService.For<IDevice>("http://localhost");              
var dev = await device.GetDevice("15e2a691-06df-4741-b26e-87e1eecc6bd7", "Bearer OAUTH_TOKEN");

3 ответа

Решение

Наконец-то я нашел способ установить время ожидания для запроса в Refit. я использовал CancelationToken, Вот модифицированный код после добавления CancelationToken

Интерфейс:

interface IDevice
{
  [Get("/app/device/{id}")]
  Task<Device> GetDevice(string id, [Header("Authorization")] string authorization, CancellationToken cancellationToken);
}

Вызов API:

var device = RestService.For<IDevice>("http://localhost");    
CancellationTokenSource tokenSource = new CancellationTokenSource();
tokenSource.CancelAfter(10000); // 10000 ms
CancellationToken token = tokenSource.Token;          
var dev = await device.GetDevice("15e2a691-06df-4741-b26e-87e1eecc6bd7", "Bearer OAUTH_TOKEN", token);

Это работает правильно для меня. Я не знаю, правильно ли это или нет. Если это неправильно, пожалуйста, предложите правильный путь.

Принятый ответ - это верный способ принудительно установить тайм-аут для одного запроса, но если вы хотите, чтобы для всех запросов было одно и то же значение времени ожидания, вы можете передать предварительно сконфигурированный HttpClient с этими Timeout набор свойств:

var api = RestService.For<IDevice>(new HttpClient 
{
    BaseAddress = new Uri("http://localhost"),
    Timeout = TimeSpan.FromSeconds(10)
});

Вот пример проекта.

Другое решение: один из тестов в Refit использует этот метод. Добавьте System.Reactive.Linq в nuget. Затем в спецификации интерфейса:

      interface IDevice
{
    [Get("/app/device/{id}")]
    IObservable<Device> GetDevice(string id, [Header("Authorization")] string authorization);
}

И в API:

      try
{
  await device.GetDevice("your_parameters_here").Timeout(TimeSpan.FromSeconds(10));
}
catch(System.TimeoutException e)
{
  Console.WriteLine("Timeout: " + e.Message);
}

+1 решение отсюда :

Создайте метод расширения для ваших задач:

      public static class TaskExtensions
{
    public static async Task<TResult> TimeoutAfter<TResult>(this Task<TResult> task, TimeSpan timeout)
    {

        using (var timeoutCancellationTokenSource = new CancellationTokenSource())
        {

            var completedTask = await Task.WhenAny(task, Task.Delay(timeout, timeoutCancellationTokenSource.Token));
            if (completedTask == task)
            {
                timeoutCancellationTokenSource.Cancel();
                return await task;  // Very important in order to propagate exceptions
            }
            else
            {
                throw new TimeoutException("The operation has timed out.");
            }
        }
    }
}

Интерфейс можно оставить с помощью Task<Device>возвращаемое значение. В API:

      try
{
  await _server.ListGasLines().TimeoutAfter(TimeSpan.FromSeconds(10));
}
catch(System.TimeoutException e)
{
  Console.WriteLine("Timeout: " + e.Message);
}
Другие вопросы по тегам