10

我在我的 Xamarin 应用程序中使用 Refit 库,我想为请求设置 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");
4

3 回答 3

24

接受的答案是对单个请求强制超时的正确方法,但是如果您想为所有请求设置一个一致的超时值,您可以传递一个HttpClient带有其Timeout属性集的预配置:

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

这是一个示例项目

于 2017-09-12T20:59:50.797 回答
17

我终于找到了一种在 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);

它适用于我。我不知道这是否是正确的方法。如果是错误的,请提出正确的方法。

于 2017-04-10T10:03:04.063 回答
0

另一种解决方案:Refit 中的一个测试使用了这种方法。在 nuget 中添加System.Reactive.Linq 。然后在接口规范中:

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);
}
于 2021-12-29T10:17:11.757 回答