private void PollingLoop(IConnection connection, string data, Action initializeCallback, Action<Exception> errorCallback, bool raiseReconnect = false)
        {
            string url = connection.Url;
            var reconnectTokenSource = new CancellationTokenSource();
            int reconnectFired = 0;

            // This is only necessary for the initial request where initializeCallback and errorCallback are non-null
            int callbackFired = 0;

            if (connection.MessageId == null)
            {
                url += "connect";
            }
            else if (raiseReconnect)
            {
                url += "reconnect";

                connection.State = ConnectionState.Reconnecting;
            }

            url += GetReceiveQueryString(connection, data);

            Debug.WriteLine("LP: {0}", (object)url);

            _httpClient.PostAsync(url, PrepareRequest(connection)).ContinueWith(task =>
            {
                // Clear the pending request
                connection.Items.Remove(HttpRequestKey);

                bool shouldRaiseReconnect = false;
                bool disconnectedReceived = false;

                try
                {
                    if (!task.IsFaulted)
                    {
                        if (raiseReconnect)
                        {
                            // If the timeout for the reconnect hasn't fired as yet just fire the
                            // event here before any incoming messages are processed
                            FireReconnected(connection, reconnectTokenSource, ref reconnectFired);
                        }

                        // Get the response
                        var raw = task.Result.ReadAsString();

                        Debug.WriteLine("LP Receive: {0}", (object)raw);

                        ProcessResponse(connection, raw, out shouldRaiseReconnect, out disconnectedReceived);
                    }
                }
                finally
                {
                    if (disconnectedReceived)
                    {
                        connection.Stop();
                    }
                    else
                    {
                        bool requestAborted = false;

                        if (task.IsFaulted)
                        {
                            // Cancel the previous reconnect event
                            reconnectTokenSource.Cancel();

                            // Raise the reconnect event if we successfully reconnect after failing
                            shouldRaiseReconnect = true;

                            // Get the underlying exception
                            Exception exception = task.Exception.GetBaseException();

                            // If the error callback isn't null then raise it and don't continue polling
                            if (errorCallback != null &&
                                Interlocked.Exchange(ref callbackFired, 1) == 0)
                            {
                                // Call the callback
                                errorCallback(exception);
                            }
                            else
                            {
                                // Figure out if the request was aborted
                                requestAborted = IsRequestAborted(exception);

                                // Sometimes a connection might have been closed by the server before we get to write anything
                                // so just try again and don't raise OnError.
                                if (!requestAborted && !(exception is IOException))
                                {
                                    // Raise on error
                                    connection.OnError(exception);

                                    // If the connection is still active after raising the error event wait for 2 seconds
                                    // before polling again so we aren't hammering the server
                                    TaskAsyncHelper.Delay(_errorDelay).Then(() =>
                                    {
                                        if (!connection.IsDisconnecting())
                                        {
                                            PollingLoop(connection,
                                                data,
                                                initializeCallback: null,
                                                errorCallback: null,
                                                raiseReconnect: shouldRaiseReconnect);
                                        }
                                    });
                                }
                            }
                        }
                        else
                        {
                            if (!connection.IsDisconnecting())
                            {
                                // Continue polling if there was no error
                                PollingLoop(connection,
                                            data,
                                            initializeCallback: null,
                                            errorCallback: null,
                                            raiseReconnect: shouldRaiseReconnect);
                            }
                        }
                    }
                }
            });

            if (initializeCallback != null)
            {
                if (Interlocked.Exchange(ref callbackFired, 1) == 0)
                {
                    initializeCallback();
                }
            }

            if (raiseReconnect)
            {
                TaskAsyncHelper.Delay(ReconnectDelay).Then(() =>
                {
                    // Fire the reconnect event after the delay. This gives the
                    FireReconnected(connection, reconnectTokenSource, ref reconnectFired);
                });
            }
        }
        private void Reconnect(IConnection connection, string data)
        {
            if (connection.IsDisconnecting())
            {
                return;
            }

            // Wait for a bit before reconnecting
            TaskAsyncHelper.Delay(ReconnectDelay).Then(() =>
            {
                // Now attempt a reconnect
                OpenConnection(connection, data, initializeCallback: null, errorCallback: null);
            });
        }