【发布时间】:2021-08-12 10:18:59
【问题描述】:
最近我在移动设备上调用 API 端点时遇到了几个问题。我的模拟器从来没有遇到过这个问题(因为网络更好),但我终于可以重现它了。
所以会发生以下情况: 用户启动他们的应用程序并调用多个 API 端点来检索数据。然而,其中一些 API 端点需要很长时间。
所以API调用设置如下:
public async Task<bool> GetData()
{
Task.Run(async () =>
{
if (App.elementsSynced == false)
await _oDataService.GetElements(_userId, _token);
// .... more code
}
}
所有调用 GetData() 的(顶级)方法也是异步的,等待调用。
GetElements():
public async Task GetElements(string userId, string token)
{
if (App.elementsSynced == true)
{
return;
}
try
{
var apiEndpointUri = new Uri(_apiUri, $"GetElements(UserId='{userId}')");
var httpRequestMessage = new HttpRequestMessage(HttpMethod.Get, apiEndpointUri);
httpRequestMessage.Headers.Add("Authorization", $"Bearer {token}");
var response = await _httpClient.SendAsync(httpRequestMessage);
HttpStatusCode statusCode = response.StatusCode;
var responseResult = await response.Content.ReadAsStringAsync();
if (statusCode != HttpStatusCode.OK)
{
// ... code omitted
return;
}
// .. saving data locally
App.elementsSynced = true;
return;
}
catch (Exception ex)
{
}
}
当有稳定的互联网连接时,上面的代码可以正常工作,但是当它需要很长时间并且我不知道确切的阈值是多少时,那么正在调用的结果是在
var response = await _httpClient.SendAsync(httpRequestMessage);
永远不会被返回,当数据在大约 60 秒后返回时也不会被返回(用 60 秒的阈值对其进行测试)。
我通过在我的 API 端点中设置断点并等待大约 60 秒左右来重现此问题。当我在 60 秒后恢复 API 并且正在发回数据时,它永远不会到达调用者(Xamarin APP)。
是否存在 http 请求不再返回结果的“隐藏”超时?我知道.NET 5 引入了TimeoutException,我可以在HttpClient 中设置超时时使用它,但我不知道(最大)超时应该是多少。默认值是 100 秒,所以我希望在 100 秒后它无论如何都应该属于异常,但它不会..
【问题讨论】:
-
您正在使用 Task.Run() 在自己的任务中调用 GetElements。我不会这样做,GetElements 是等待的。因此,您可以在 GetData 中调用 await GetElements() 并尝试捕获异常。
-
我也对这样做有所保留,但最后我希望在其余逻辑(和 UI)继续运行的同时运行“同步”方法。现在我在启动方法 (
IntializeAsync) 中调用GetData(),如果我要删除Task.Run,那么所有 API 端点必须在 UI/其余逻辑继续之前完成? -
您可以拆分方法调用并等待:
var task = _oDataService.GetElements(_userId, _token); /* Do some work */ await task;如果您需要的话。 -
不完全。 APP在一个'LoginViewModel'中启动,登录成功后,继续登录代码并开始'同步'。在同步运行时,用户被重定向到第一个数据页面(例如 HomeView)。登录后的每个 View/ViewModel 都会检查该页面的数据是否已加载,这些“检查”变量在特定的 Get{dataname} 方法中设置。 API 返回结果后,该变量被设置为 true。所以这意味着我必须像你描述的那样将
var task设为全局,可以从(其他)ViewModels访问? -
但也许我做错了 :) 我对移动开发/API 同步数据很陌生。
标签: c# xamarin.forms