private async Task <byte[]> GetBytesAsyncInner([NotNull] string url, string cacheKey = null, TimeSpan?aliveTime = null, IProgress <long> progress = null, CancellationToken cancellation = default) { try { if (cacheKey == null) { cacheKey = GetTemporaryName(url); } var actualAliveTime = aliveTime ?? _cacheAliveTime; Tuple <byte[], DateTime> cache; lock (_cache) { cache = _cache.GetValueOrDefault(cacheKey); } if (cache != null && cache.Item2 > DateTime.Now - actualAliveTime) { return(cache.Item1); } var cacheFile = new FileInfo(FilesStorage.Instance.GetTemporaryFilename(_directory, cacheKey)); if (cacheFile.Exists && cacheFile.LastWriteTime > DateTime.Now - actualAliveTime) { try { var data = await FileUtils.ReadAllBytesAsync(cacheFile.FullName).ConfigureAwait(false); lock (_cache) { _cache[cacheKey] = Tuple.Create(data, cacheFile.LastWriteTime); } return(data); } catch (Exception e) { Logging.Warning(e); try { cacheFile.Delete(); } catch { // ignored } } } try { var request = new HttpRequestMessage(HttpMethod.Get, url); using (var timeout = new CancellationTokenSource(KunosApiProvider.OptionWebRequestTimeout)) using (var combined = CancellationTokenSource.CreateLinkedTokenSource(cancellation, timeout.Token)) using (var response = await HttpClientHolder.Get().SendAsync(request, HttpCompletionOption.ResponseHeadersRead, combined.Token).ConfigureAwait(false)) { byte[] data; if (progress == null) { data = await response.Content.ReadAsByteArrayAsync().ConfigureAwait(false); } else { using (var memory = new MemoryStream()) using (var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false)) { await CopyToAsync(stream, memory, progress, cancellation).ConfigureAwait(false); cancellation.ThrowIfCancellationRequested(); data = memory.ToArray(); } } if (data.Length < 1e6) { lock (_cache) { _cache[cacheKey] = Tuple.Create(data, DateTime.Now); } if (actualAliveTime > TimeSpan.Zero) { try { File.WriteAllBytes(cacheFile.FullName, data); } catch (Exception e) { Logging.Warning(e); } } } return(data); } } catch (Exception e) { if (!cancellation.IsCancellationRequested) { Logging.Warning(e); } if (cache != null) { return(cache.Item1); } if (cacheFile.Exists) { var data = await FileUtils.ReadAllBytesAsync(cacheFile.FullName).ConfigureAwait(false); lock (_cache) { _cache[cacheKey] = Tuple.Create(data, cacheFile.LastWriteTime); } return(data); } return(null); } } finally { _tasks.Remove(url); } }