示例#1
0
        /// <summary>Called after an HTTP request has been processed in any way (error or failure). Decides what to do next.</summary>
        protected void FinishWithRequest(WebRequest state, HttpResponse response)
        {
            // This "hack" is needed because sometimes the callback is called multiple times for a single request (notably from RespCallback)
            if (state.AlreadyFinished) return;
            state.AlreadyFinished = true;
            // IDEA This function could probably be moved to another file with a little gymnastic…
            HttpRequest nextReq;
            // Avoid timeout to be triggered after that
            AllDone.Set();
            lock (this) {
                // No need to continue, dismiss the result
                if (Terminated) return;
                RunningRequests.Remove(state);
            }
            // Has failed?
            if (response.ShouldBeRetried(state.OriginalRequest) && !state.Aborted) {
                if (state.OriginalRequest.FailedHandler != null) {
                    // See whether to try again
                    var eventArgs = new HttpRequestFailedEventArgs(state.OriginalRequest, state.PreviousUserData);
                    // Invoke the failure handler
                    try {
                        state.OriginalRequest.FailedHandler(eventArgs);
                        if (eventArgs.RetryDelay < 0) throw new InvalidOperationException("HTTP request failed handler called but didn't tell what to do next.");
                        if (eventArgs.RetryDelay > 0) {
                            Common.LogWarning("[" + state.RequestId + "] Request failed, retrying in " + eventArgs.RetryDelay + "ms.");
                            Thread.Sleep(eventArgs.RetryDelay);
                            ChooseLoadBalancer(state.OriginalRequest);
                            ProcessRequest(state.OriginalRequest, eventArgs.UserData);
                            return;
                        }
                    }
                    catch (Exception e) {
                        Common.LogError("Error in failure handler: " + e.ToString());
                    }
                }
                // Maximum failure count reached, will simply process the next request
                Common.LogWarning("[" + state.RequestId + "] Request failed.");
            }
            // Final result for this request
            if (state.OriginalRequest.Callback != null) {
                Cotc.RunOnMainThread(() => state.OriginalRequest.Callback(response));
            }
            // Was independent?
            if (state.OriginalRequest.DoNotEnqueue) return;

            // Process next request
            lock (this) {
                // Note: currently another request is only launched after synchronously processed by the callback. This behavior is slower but might be safer.
                if (!state.OriginalRequest.DoNotEnqueue && PendingRequests.Count == 0) {
                    IsProcessingRequest = false;
                    return;
                }
                nextReq = PendingRequests[0];
                PendingRequests.RemoveAt(0);
            }
            ProcessRequest(nextReq);
        }