在Xamarin/中处理重复HTTPClient调用的最佳方式是什么.NET



我正在研制Xamarin。窗体Android应用程序,要求手机每15秒ping一次服务器。我的所有调用都是异步的,并且都有"await"属性,这包括在Device中找不到的主要类中的所有主要用户函数。StartTimer对象。例如,单击按钮注册数据、登录和注销。对于15秒的ping,我使用的是设备。StartTimer函数和我没有遇到太多问题,但有时我确实注意到响应确实重叠,但我认为"等待"声明会处理重叠的响应,因为我阅读了该设备。StartTimer在主线程上工作。我做错了什么?是否有更好的方法来管理定时HTTPClient调用?

我尝试将await属性应用于函数,以确保调用不会重叠。有一条关于设备的注释。StartTimer在主线程上运行,所以我认为我的所有异步等待函数都会得到尊重。在主要类中包括异步函数。

//Function to ping to the server every 15 seconds
private void StartOfflineTimer()
{
Device.StartTimer(TimeSpan.FromSeconds(15.0), () =>
{
if(timerOffline)
{
Task.Run(async () =>
if(await InformarOfflineAsync(Settings.AccessToken, idRutaOffline))
{
DependencyService.Get<ILogUtils>().GuardarLine("**Device conected.."); 
}
else
{
DependencyService.Get<ILogUtils>().GuardarLine("**Device disconnected..");
}
);
}
return timerOffline;
});
}
//Default Example of how I handle ALL HTTPClient calls on the app, including calls that are in the main classes, not embedded in a device timer. All of these calls are inside their own public async Task<ExampleObject> function. Once again all of the functions that make these calls have an "await" attribute.

var jsonRequest = await Task.Run(() => JsonConvert.SerializeObject(requestObj));
var httpContent = new StringContent(jsonRequest, Encoding.UTF8, "application/json");
using (var httpClient = new HttpClient())
{
httpClient.Timeout = TimeSpan.FromSeconds(10.0);
var httpResponse = await httpClient.PostAsync(Constants.BaseUrl + "login/validarOffline", httpContent);
ExampleObjectResponseObj exampleObject = new ExampleObjectResponseObj();
var responseContent = await httpResponse.Content.ReadAsStringAsync();
ExampleObjectResponseObj = JsonConvert.DeserializeObject<InformDataResponseObj>(responseContent);
return ExampleObjectResponseObj;
}

HTTPClient响应可能重叠,或者有时它们会加倍并同时发送。

如果你不想让你的呼叫重叠,不要使用定时器,而是使用一个有延迟的循环:

Task.Run(async () =>
{
const TimeSpan checkInterval = TimeSpan.FromSeconds(15);
while (true)
{
var callTime = DateTime.UtcNow;
try
{
await server.Ping();
}
catch (Exception exception)
{
HandleException(exception);
}
var elapsedTime = DateTime.UtcNow - callTime;
var timeToWait = checkInterval - elapsedTime;
if (timeToWait > TimeSpan.Zero)
{
await Task.Delay(timeToWait);
}
}
});

上面的代码并不完整,不足以给出非常详细和精确的答案,但即使不是所有的事情,也可以回答:

  • 您在Task.Run中运行计时器回调,因此它不在主线程中运行
  • 如果你想在UI线程中运行HttpClient,它可能会防止重叠,但预计你的应用程序会完全没有响应
  • 为了防止重叠,您可以使用几种方法,但很可能您正在寻找SemaphoreSlim

最新更新