private IEnumerable<Task> _AsyncSteps(HttpWebRequest request, TaskCompletionSource<ElasticsearchResponse> tcs, byte[] data = null)
        {
            using (var tracer = new ElasticsearchResponseTracer(this._ConnectionSettings.TraceEnabled))
            {
                var timeout = this._ConnectionSettings.Timeout;

                var state = new ConnectionState { Connection = request };

                if (data != null)
                {
                    var getRequestStream = Task.Factory.FromAsync<Stream>(request.BeginGetRequestStream, request.EndGetRequestStream, null);
                    //ThreadPool.RegisterWaitForSingleObject((getRequestStream as IAsyncResult).AsyncWaitHandle, ThreadTimeoutCallback, request, timeout, true);
                    yield return getRequestStream;

                    var requestStream = getRequestStream.Result;
                    try
                    {
                        var writeToRequestStream = Task.Factory.FromAsync(requestStream.BeginWrite, requestStream.EndWrite, data, 0, data.Length, state);
                        yield return writeToRequestStream;
                    }
                    finally
                    {
                        requestStream.Close();
                    }
                }

                // Get the response
                var getResponse = Task.Factory.FromAsync<WebResponse>(request.BeginGetResponse, request.EndGetResponse, null);
                //ThreadPool.RegisterWaitForSingleObject((getResponse as IAsyncResult).AsyncWaitHandle, ThreadTimeoutCallback, request, timeout, true);
                yield return getResponse;

                var path = request.RequestUri.ToString();
                var method = request.Method;

                // Get the response stream
                using (var response = (HttpWebResponse)getResponse.Result)
                using (var responseStream = response.GetResponseStream())
                using (var memoryStream = new MemoryStream())
                {
                    // Copy all data from the response stream
                    var buffer = new byte[BUFFER_SIZE];
                    while (responseStream != null)
                    {
                        var read = Task<int>.Factory.FromAsync(responseStream.BeginRead, responseStream.EndRead, buffer, 0, BUFFER_SIZE, null);
                        yield return read;
                        if (read.Result == 0) break;
                        memoryStream.Write(buffer, 0, read.Result);
                    }
                    var cs = ElasticsearchResponse.Create(this._ConnectionSettings, (int) response.StatusCode, method, path, data, memoryStream.ToArray());
                    tcs.TrySetResult(cs);
                    tracer.SetResult(cs);
                    _ConnectionSettings.ConnectionStatusHandler(cs);
                }
            }
        }
        private IEnumerable<Task> _AsyncSteps(HttpWebRequest request, TaskCompletionSource<ElasticsearchResponse<Stream>> tcs, byte[] data, object requestSpecificConfig)
        {
            var timeout = this.ConnectionSettings.Timeout;

            var state = new ConnectionState { Connection = request };

            if (data != null)
            {
                var getRequestStream = Task.Factory.FromAsync<Stream>(request.BeginGetRequestStream, request.EndGetRequestStream, null);
                //ThreadPool.RegisterWaitForSingleObject((getRequestStream as IAsyncResult).AsyncWaitHandle, ThreadTimeoutCallback, request, timeout, true);
                yield return getRequestStream;

                var requestStream = getRequestStream.Result;
                try
                {
                    var writeToRequestStream = Task.Factory.FromAsync(requestStream.BeginWrite, requestStream.EndWrite, data, 0, data.Length, state);
                    yield return writeToRequestStream;
                }
                finally
                {
                    requestStream.Close();
                }
            }

            // Get the response
            var getResponse = Task.Factory.FromAsync<WebResponse>(request.BeginGetResponse, request.EndGetResponse, null);
            //ThreadPool.RegisterWaitForSingleObject((getResponse as IAsyncResult).AsyncWaitHandle, ThreadTimeoutCallback, request, timeout, true);
            yield return getResponse;

            var path = request.RequestUri.ToString();
            var method = request.Method;

            //http://msdn.microsoft.com/en-us/library/system.net.httpwebresponse.getresponsestream.aspx
            //Either the stream or the response object needs to be closed but not both (although it won't)
            //throw any errors if both are closed atleast one of them has to be Closed.
            //Since we expose the stream we let closing the stream determining when to close the connection
            var response = (HttpWebResponse)getResponse.Result;
            var responseStream = response.GetResponseStream();
            var cs = ElasticsearchResponse<Stream>.Create(this.ConnectionSettings, (int)response.StatusCode, method, path, data);
            cs.Response = responseStream;
            tcs.TrySetResult(cs);
        }