private async void Run(HttpClient client) { var hadFailed = false; for (; ;) { Item item; lock (_Items) { for (; ;) { if (_Items.Count == 0) { return; } item = _Items[0]; if (item.Retry <= 0 || item.CompletionSource.Task.IsCompleted) { _Items.RemoveAt(0); } else { break; } } } try { var wait = _LastRequest.AddMilliseconds(_Interval) - DateTime.Now; if (wait > TimeSpan.Zero) { await Task.Delay(wait); } var url = new SignedRequestHelper(AccessKeyId, SecretKey, "webservices." + item.Destination).Sign(new Dictionary <string, string>() { ["Service"] = "AWSECommerceService", ["Operation"] = "ItemLookup", ["AWSAccessKeyId"] = AccessKeyId, ["AssociateTag"] = AssociateTag, ["ItemId"] = item.Asin, ["IdType"] = "ASIN", ["ResponseGroup"] = "Images,ItemAttributes,EditorialReview", }); var res = (await client.FollowRedirectAsync(url.ToUri()).ConfigureAwait(false)).Message; _LastRequest = DateTime.Now; if (res.StatusCode == HttpStatusCode.ServiceUnavailable) { if (hadFailed) { _Interval = Math.Min(1280, _Interval << 1); } else { hadFailed = true; } continue; } hadFailed = false; res.EnsureSuccessStatusCode(); var s = await res.Content.ReadAsStringAsync().ConfigureAwait(false); item.CompletionSource.TrySetResult(ParseResponse(s, item)); } catch (Exception ex) { lock (_Items) { if (--item.Retry > 0) { continue; } else { _Items.Remove(item); } } item.CompletionSource.TrySetException(ex); } } }