public async Task WriteToAsync(Stream destination, int bufferSize,
            CancellationToken cancellationToken = default(CancellationToken), TaskProgressEventHandler progressHandler = null, TaskCompleteEventHandler completeHandler = null)
        {
            byte[] buffer = null;

            foreach (Stream currentStream in streams)
            {
                currentStream.Position = 0;

                if (cancellationToken.IsCancellationRequested)
                    return;

                // Purely for progress purposes
                double totalRead = new double();

                if (currentStream is MemoryStream)
                {
                    // MemoryStream: Get underlying buffer
                    MemoryStream memoryStream = (MemoryStream)currentStream;

                    // MemoryStream: Check if underlying buffer is valid
                    bool bufferValid = false;
                    try
                    {
                        buffer = memoryStream.GetBuffer();
                        bufferValid = buffer != null;
                    }
                    catch { }

                    if (bufferValid)
                    {
                        // MemoryStream Buffer: Buffer is valid and can be used
                        int readPosition = new int();

                        while (readPosition < memoryStream.Length && !cancellationToken.IsCancellationRequested)
                        {
                            // ProgressHandler: Begin asynchronous invoke
                            IAsyncResult progressHandlerResult = null;
                            if (progressHandler != null)
                                progressHandlerResult = progressHandler.BeginInvoke(Math.Min(1.0, totalRead / (double)_length), null, null);

                            // WriteTask: Start writing to stream asynchronously
                            int chunk = (int) Math.Min(memoryStream.Length - readPosition, bufferSize);
                            Task writeTask = destination.WriteAsync(buffer, readPosition, chunk, cancellationToken);

                            // ProgressHandler: End asynchronous invoke
                            if (progressHandler != null && progressHandlerResult != null)
                                progressHandler.EndInvoke(progressHandlerResult);

                            // WriteTask: Wait for chunk upload to finish
                            await writeTask;
                            totalRead += chunk;
                            readPosition += chunk;
                        }
                        // Go onto next stream
                        continue;
                    }

                    // MemoryStream Buffer: Buffer was not valid - fall through to next case
                }

                if (buffer == null || buffer.Length < bufferSize)
                    buffer = new byte[bufferSize];

                int chunkRead;
                while ((chunkRead = await currentStream.ReadAsync(buffer, 0, bufferSize)) > 0 && !cancellationToken.IsCancellationRequested)
                {
                    // ProgressHandler: Begin asynchronous invoke
                    IAsyncResult progressHandlerResult = null;
                    if (progressHandler != null)
                        progressHandlerResult = progressHandler.BeginInvoke(Math.Min(1.0, (double)totalRead / (double)_length), null, null);

                    // WriteTask: Start writing to stream asynchronously
                    Task writeTask = destination.WriteAsync(buffer, 0, chunkRead, cancellationToken);

                    // ProgressHandler: End asynchronous invoke
                    if (progressHandler != null && progressHandlerResult != null)
                        progressHandler.EndInvoke(progressHandlerResult);

                    // WriteTask: Wait for write to finish
                    await writeTask;
                    totalRead += chunkRead;
                }
            }
        }
 /// <summary>
 /// Asynchronously reads the content of an HTTP response as a UTF-8 encoded string.
 /// </summary>
 /// <param name="response">Required. The HttpWebResponse object representing the response to read.</param>
 /// <param name="disposeResponse">Optional. A boolean value determining whether to dispose of the response when finished. The default is true.</param>
 /// <param name="cancellationToken">Optional. The token to monitor for cancellation requests.</param>
 /// <param name="progressHandler">Optional. The event handler to invoke when progress has changed.</param>
 /// <param name="completeHandler">Optional. The event handler to invoke when the response has been read.</param>
 /// <returns>Returns a Task object containing a string result representing the content of the response.</returns>
 public static async Task<string> ToUTF8Async(this HttpWebResponse response, bool disposeResponse = true,
     CancellationToken cancellationToken = default(CancellationToken), TaskProgressEventHandler progressHandler = null, TaskCompleteEventHandler completeHandler = null)
 {
     return Encoding.UTF8.GetString(await ToArrayAsync(response, disposeResponse, cancellationToken, progressHandler, completeHandler));
 }
        /// <summary>
        /// Asynchronously performs an HttpWebRequest with request data.
        /// </summary>
        /// <param name="request">Required. The HttpWebRequest to represent the base request.</param>
        /// <param name="contentType">Required. The Content-Type HTTP header to send with the request.</param>
        /// <param name="data">Required. A byte array representing the request data to send with the request.</param>
        /// <param name="cancellationToken">Optional. The token to monitor for cancellation requests.</param>
        /// <param name="progressHandler">Optional. The event handler to invoke when progress has changed.</param>
        /// <param name="completeHandler">Optional. The event handler to invoke when the request has finished.</param>
        /// <returns>Returns a HttpWebResponse representing the response from the server.</returns>
        public async Task<HttpWebResponse> RequestAsync(HttpWebRequest request, string contentType, byte[] data,
            CancellationToken cancellationToken = default(CancellationToken), TaskProgressEventHandler progressHandler = null, TaskCompleteEventHandler completeHandler = null)
        {
            request.ContentLength = (data != null) ? data.Length : 0;

            if (!String.IsNullOrEmpty(contentType))
                request.ContentType = contentType;

            // Write to request stream
            using (Stream requestStream = await request.GetRequestStreamAsync())
            {
                int bufferSize = GetOptimalBufferSize(data.Length);
                int bytesDone = new int();

                while (bytesDone < data.Length)
                {
                    // ProgressHandler: Begin asynchronous invoke
                    IAsyncResult progressHandlerResult = null;
                    if (progressHandler != null)
                        progressHandlerResult = progressHandler.BeginInvoke(Math.Min(1.0, (double)bytesDone / (double)data.Length), null, null);

                    // WriteTask: Start writing to stream asynchronously
                    int nextChunkSize = Math.Min(data.Length - bytesDone, bufferSize);
                    Task writeTask = requestStream.WriteAsync(data, bytesDone, nextChunkSize, cancellationToken);                    

                    // End asynchronous ProgressHandler
                    if (progressHandler != null && progressHandlerResult != null)
                        progressHandler.EndInvoke(progressHandlerResult);

                    // WriteTask: Wait for chunk upload to finish
                    await writeTask;
                    bytesDone += nextChunkSize;
                }
            }

            HttpWebResponse result;

            {
                // HttpWebResponse: Start task
                Task<WebResponse> resultTask = request.GetResponseAsync();

                // CompleteHandler: Begin asynchronous invoke
                IAsyncResult completeHandlerResult = null;
                if (completeHandler != null)
                    completeHandler.BeginInvoke(null, null);

                // HttpWebResponse: Await result
                result = (HttpWebResponse)(await resultTask);

                // CompleteHandler: End asynchronous invoke
                if (completeHandler != null && completeHandlerResult != null)
                    completeHandler.EndInvoke(completeHandlerResult);
            }

            return result;
        }
        /// <summary>
        /// Asynchronously reads the content of an HTTP response to a byte array.
        /// </summary>
        /// <param name="response">Required. The HttpWebResponse object representing the response to read.</param>
        /// <param name="disposeResponse">Optional. A boolean value determining whether to dispose of the response when finished. The default is true.</param>
        /// <param name="cancellationToken">Optional. The token to monitor for cancellation requests.</param>
        /// <param name="progressHandler">Optional. The event handler to invoke when progress has changed.</param>
        /// <param name="completeHandler">Optional. The event handler to invoke when the response has been read.</param>
        /// <returns>Returns a Task object containing a byte array result representing the content of the response.</returns>
        public static async Task<byte[]> ToArrayAsync(this HttpWebResponse response, bool disposeResponse = true,
            CancellationToken cancellationToken = default(CancellationToken), TaskProgressEventHandler progressHandler = null, TaskCompleteEventHandler completeHandler = null)
        {
            byte[] result;
            if (response.ContentLength > 0)
            {
                long contentLength = response.ContentLength;
                result = new byte[contentLength];
                int bufferSize = Http_Old.GetOptimalBufferSize(contentLength);

                using (Stream responseStream = response.GetResponseStream())
                {
                    long bytesRead = 0;

                    // ReadTask: Start reading before first iteration.
                    int chunkRead = await responseStream.ReadAsync(result, 0, (int)Math.Min(contentLength - bytesRead, bufferSize), cancellationToken);
                    bytesRead += chunkRead;

                    while (bytesRead < contentLength && chunkRead > 0 && !cancellationToken.IsCancellationRequested)
                    {
                        // ProgressHandler: Begin asynchronous invoke
                        IAsyncResult progressHandlerResult = null;
                        if (progressHandler != null)
                            progressHandlerResult = progressHandler.BeginInvoke(Math.Min(1.0, (double)bytesRead / (double)contentLength), null, null);

                        // ReadTask: Start another read asynchronously
                        Task<int> readTask = responseStream.ReadAsync(result, 0, (int)Math.Min(contentLength - bytesRead, bufferSize), cancellationToken);

                        // ProgressHandler: End asynchronous invoke
                        if (progressHandler != null && progressHandlerResult != null)
                            progressHandler.EndInvoke(progressHandlerResult);

                        // WriteTask: Wait for chunk to finish
                        chunkRead = await readTask;
                        bytesRead += chunkRead;
                    }
                }
            }
            else
            {
                int bufferSize = Http_Old.GetOptimalBufferSize(-1);
                using (MemoryStream memory = new MemoryStream(bufferSize))
                {
                    using (Stream responseStream = response.GetResponseStream())
                    {
                        byte[] buffer = new byte[bufferSize];
                        long bytesRead = 0;
                        int chunkRead;

                        while ((chunkRead = await responseStream.ReadAsync(buffer, 0, bufferSize)) > 0)
                        {
                            // ProgressHandler: Begin asynchronous invoke
                            IAsyncResult progressHandlerResult = null;
                            if (progressHandler != null && response.ContentLength > 0)
                                progressHandlerResult = progressHandler.BeginInvoke(Math.Min(1.0, (double)bytesRead / (double)response.ContentLength), null, null);

                            // WriteTask: Start writing to memory asynchronously
                            Task writeTask = memory.WriteAsync(buffer, 0, chunkRead, cancellationToken);

                            // End asynchronous ProgressHandler
                            if (progressHandler != null && progressHandlerResult != null)
                                progressHandler.EndInvoke(progressHandlerResult);

                            // WriteTask: Wait for chunk to finish
                            await writeTask;
                            bytesRead += chunkRead;
                        }
                    }

                    result = memory.ToArray();
                }
            }

            if (disposeResponse)
                response.Close();

            return result;
        }
        /// <summary>
        /// Asynchronously performs an HttpWebRequest with request data.
        /// </summary>
        /// <param name="request">Required. The HttpWebRequest to represent the base request.</param>
        /// <param name="contentType">Required. The Content-Type HTTP header to send with the request.</param>
        /// <param name="formData">Required. A FormBuilder object representing the form data to send.</param>
        /// <param name="cancellationToken">Optional. The token to monitor for cancellation requests.</param>
        /// <param name="progressHandler">Optional. The event handler to invoke when progress has changed.</param>
        /// <param name="completeHandler">Optional. The event handler to invoke when the request has finished.</param>
        /// <returns>Returns a HttpWebResponse representing the response from the server.</returns>
        public async Task<HttpWebResponse> RequestAsync(HttpWebRequest request, FormBuilder formData,
            CancellationToken cancellationToken = default(CancellationToken), TaskProgressEventHandler progressHandler = null, TaskCompleteEventHandler completeHandler = null)
        {
            request.ContentLength = formData.Length;

            if (!String.IsNullOrEmpty(formData.ContentType))
                request.ContentType = formData.ContentType;

            // Write to request stream
            using (Stream requestStream = await request.GetRequestStreamAsync())
            {
                await formData.WriteToAsync(requestStream, GetOptimalBufferSize(formData.Length));
            }

            HttpWebResponse result;

            {
                // HttpWebResponse: Start task
                Task<WebResponse> resultTask = request.GetResponseAsync();

                // CompleteHandler: Begin asynchronous invoke
                IAsyncResult completeHandlerResult = null;
                if (completeHandler != null)
                    completeHandler.BeginInvoke(null, null);

                // HttpWebResponse: Await result
                result = (HttpWebResponse)(await resultTask);

                // CompleteHandler: End asynchronous invoke
                if (completeHandler != null && completeHandlerResult != null)
                    completeHandler.EndInvoke(completeHandlerResult);
            }

            return result;
        }