I have the following code for checking availability applications from play market and app store:
public async Task<List<CheckPackageResponse>> CheckAsync(List<string> appIds)
{
var sem = new SemaphoreSlim(200);
var tasks = appIds.Select(async (a, i) =>
{
await sem.WaitAsync();
var response = new CheckPackageResponse
{
AppId = a,
};
string url;
// if IOS
if (a.All(Char.IsDigit))
{
url = $"https://apps.apple.com/ru/app/id{a}?dataOnly=true&isWebExpV2=true";
}
else
{
url = $"https://play.google.com/store/apps/details?id={a}";
}
try
{
_client.DefaultRequestHeaders.UserAgent.ParseAdd("Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2062.124 Safari/537.36");
var resp = await _client.GetAsync(url, HttpCompletionOption.ResponseHeadersRead);
response.HttpStatus = (int) resp.StatusCode;
return response;
}
catch (Exception e)
{
response.ErrorMessage = e.Message;
response.StackTrace = e.StackTrace;
return response;
}
finally
{
sem.Release();
}
}).ToList();
return (await Task.WhenAll(tasks)).ToList();
}
And in the Startup.cs
I have the following to inject HttpClient
:
services.AddHttpClient<ICheckPackagesService, CheckPackagesService>(x =>
{
x.Timeout = TimeSpan.FromSeconds(7);
}).ConfigurePrimaryHttpMessageHandler(() => new SocketsHttpHandler
{
Proxy = new WebProxy(Configuration["Proxy"] != "" ? Configuration["Proxy"] : null)
});
It works nice. I can give list of application ids and API will answer me is an application available or not. But it has some problem. After some time it has crash with error
Address in use.
It tells me that HTTP client does not close connections. But I know that this problem possible if I use something like this:
using(var http = new HttpClient(...)) {
...
}
And it's definitely not my case. So what is wrong in my case? Where is the mistake?
Update
I will pin here my stack trace
at System.Net.Http.ConnectHelper.ConnectAsync(String host, Int32 port, CancellationToken cancellationToken)\n at System.Threading.Tasks.ValueTask
1.get_Result()\n at System.Net.Http.HttpConnectionPool.CreateConnectionAsync(HttpRequestMessage request, CancellationToken cancellationToken)\n at System.Threading.Tasks.ValueTask
1.get_Result()\n at System.Net.Http.HttpConnectionPool.WaitForCreatedConnectionAsync(ValueTask1 creationTask)\n at System.Threading.Tasks.ValueTask
1.get_Result()\n at System.Net.Http.HttpConnectionPool.SendWithRetryAsync(HttpRequestMessage request, Boolean doRequestAuth, CancellationToken cancellationToken)\n at System.Net.Http.RedirectHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)\n at Microsoft.Extensions.Http.Logging.LoggingHttpMessageHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)\n at Microsoft.Extensions.Http.Logging.LoggingScopeHttpMessageHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)\n at System.Net.Http.HttpClient.FinishSendAsyncUnbuffered(Task`1 sendTask, HttpRequestMessage request, CancellationTokenSource cts, Boolean disposeCts)\n at ApChecker.Services.Concrete.CheckPackagesService.<>c__DisplayClass2_0.<b__0>d.MoveNext() in /builds/mobilemediaru/makeapp/apchecker/ApChecker/Services/Concrete/CheckPackagesService.cs:line 50