/// <summary>Downloads the resource with the specified URI to a local file, asynchronously.</summary>
    /// <param name="webClient">The WebClient.</param>
    /// <param name="address">The URI from which to download data.</param>
    /// <param name="fileName">The name of the local file that is to receive the data.</param>
    /// <returns>A Task that contains the downloaded data.</returns>
    public static Task DownloadFileTaskAsync(this WebClient webClient, Uri address, string fileName)
    {
        // Create the task to be returned
        var tcs = new TaskCompletionSource <object>(address);

        // Setup the callback event handler
        AsyncCompletedEventHandler completedHandler = null;

        completedHandler = (sender, e) => TaskServices.HandleEapCompletion(tcs, true, e, () => null, () =>
        {
            webClient.DownloadFileCompleted -= completedHandler;
        });
        webClient.DownloadFileCompleted += completedHandler;

        // Start the async operation.
        try
        {
            webClient.DownloadFileAsync(address, fileName, tcs);
        }
        catch
        {
            webClient.DownloadFileCompleted -= completedHandler;
            throw;
        }

        // Return the task that represents the async operation
        return(tcs.Task);
    }
    /// <summary>Downloads the resource with the specified URI as a byte array, asynchronously.</summary>
    /// <param name="webClient">The WebClient.</param>
    /// <param name="address">The URI from which to download data.</param>
    /// <returns>A Task that contains the downloaded data.</returns>
    public static Task <byte[]> DownloadDataTaskAsync(this WebClient webClient, Uri address)
    {
        // Create the task to be returned
        var tcs = new TaskCompletionSource <byte[]>(address);

        // Setup the callback event handler
        DownloadDataCompletedEventHandler completedHandler = null;

        completedHandler = (sender, e) => TaskServices.HandleEapCompletion(tcs, true, e, () => e.Result, () => webClient.DownloadDataCompleted -= completedHandler);
        webClient.DownloadDataCompleted += completedHandler;

        // Start the async operation.
        try
        {
            webClient.DownloadDataAsync(address, tcs);
        }
        catch
        {
            webClient.DownloadDataCompleted -= completedHandler;
            throw;
        }

        // Return the task that represents the async operation
        return(tcs.Task);
    }
    /// <summary>Opens a readable stream for the data downloaded from a resource, asynchronously.</summary>
    /// <param name="webClient">The WebClient.</param>
    /// <param name="address">The URI for which the stream should be opened.</param>
    /// <returns>A Task that contains the opened stream.</returns>
    public static Task <Stream> OpenReadTaskAsync(this WebClient webClient, Uri address)
    {
        // Create the task to be returned
        var tcs = new TaskCompletionSource <Stream>(address);

        // Setup the callback event handler
        OpenReadCompletedEventHandler handler = null;

        handler = (sender, e) => TaskServices.HandleEapCompletion(tcs, true, e, () => e.Result, () => webClient.OpenReadCompleted -= handler);
        webClient.OpenReadCompleted += handler;

        // Start the async operation.
        try { webClient.OpenReadAsync(address, tcs); }
        catch
        {
            webClient.OpenReadCompleted -= handler;
            throw;
        }

        // Return the task that represents the async operation
        return(tcs.Task);
    }
    /// <summary>Uploads a file to the specified resource, asynchronously.</summary>
    /// <param name="webClient">The WebClient.</param>
    /// <param name="address">The URI to which the file should be uploaded.</param>
    /// <param name="method">The HTTP method that should be used to upload the file.</param>
    /// <param name="fileName">A path to the file to upload.</param>
    /// <returns>A Task containing the data in the response from the upload.</returns>
    public static Task <byte[]> UploadFileTaskAsync(this WebClient webClient, Uri address, string method, string fileName)
    {
        // Create the task to be returned
        var tcs = new TaskCompletionSource <byte[]>(address);

        // Setup the callback event handler
        UploadFileCompletedEventHandler handler = null;

        handler = (sender, e) => TaskServices.HandleEapCompletion(tcs, true, e, () => e.Result, () => webClient.UploadFileCompleted -= handler);
        webClient.UploadFileCompleted += handler;

        // Start the async operation.
        try { webClient.UploadFileAsync(address, method, fileName, tcs); }
        catch
        {
            webClient.UploadFileCompleted -= handler;
            throw;
        }

        // Return the task that represents the async operation
        return(tcs.Task);
    }