Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to attach CancellationTokenSource to DownloadStringTaskAsync method and cancel the async call?

I an creating a sample example to call link using WebClient using async and await method now I want to attach cancel async call functionality also. But I am not able to get CancellationTokenSource token and attach DownloadStringTaskAsync to this cancellation token. Following Is my code can anyone tell me how to accomplish this.

private async void DoWork()
        {
            this.Cursor = Cursors.WaitCursor;
            Write("DoWork started.");
            cts = new CancellationTokenSource();
            WebClient wc = new WebClient();
            string result = await wc.DownloadStringTaskAsync(new Uri("http://gyorgybalassy.wordpress.com"));

            if (result.Length < 100000)
            {
                Write("The result is too small, download started from second URL.");
                result = await wc.DownloadStringTaskAsync(new Uri("https://www.facebook.com/balassy"));
            }
            Write("Download completed. Downloaded bytes: " + result.Length.ToString());
            Write("DoWork ended.");
            this.Cursor = Cursors.Default;
        }

        private void btnCancel_Click(object sender, EventArgs e)
        {
            Write("Cancellation started.");
            this.cts.Cancel();
            Write("Cancellation ended.");
        }

When my Cancel button calls cts.Cancel the DownloadStringTaskAsync call is not canceled. Why cancel button is not able to cancel the Async calls?

like image 445
Balraj Singh Avatar asked Dec 10 '12 09:12

Balraj Singh


People also ask

How do I end async method?

You can cancel an asynchronous operation after a period of time by using the CancellationTokenSource. CancelAfter method if you don't want to wait for the operation to finish.

Which method can you use to cancel an ongoing operation that uses CancellationToken?

The CancellationTokenSource token is used to signal that the Task should cancel itself. In the above case, the operation will just end when cancellation is requested via Cancel() method.

Should all async methods have cancellation token?

Description: Asynchronous methods should take a CancellationToken. Sometimes, async methods are not written with cooperative cancellation in mind. Either because a developer is not aware of the pattern or because they consider it unnecessary in a specific case.

Can you reuse CancellationTokenSource?

Yes, you can reuse CancellationTokens. A CancellationTokenSource is used to cancel a set of processes. All processes associated with a particular CancellationTokenSource will use one CancellationToken among them.


2 Answers

The async capabilities of WebClient predate .Net 4.5, so it supports the Task-based Asynchronous Pattern only partially. That includes having its own cancellation mechanism: the CancelAsync() method, which works even with the new -TaskAsync methods. To call this method when a CancellationToken is canceled, you can use its Register() method:

cts.Token.Register(wc.CancelAsync);

As an alternative, you could use the new HttpClient, as Stephen suggested, which fully supports TAP, including CancellationTokens.

like image 167
svick Avatar answered Oct 15 '22 21:10

svick


Extension methods based on svick's answer:

public static async Task<string> DownloadStringTaskAsync(this WebClient webClient, string url, CancellationToken cancellationToken) {
    using (cancellationToken.Register(webClient.CancelAsync)) {
        return await webClient.DownloadStringTaskAsync(url);
    }
}

public static async Task<string> DownloadStringTaskAsync(this WebClient webClient, Uri uri, CancellationToken cancellationToken) {
    using (cancellationToken.Register(webClient.CancelAsync)) {
        return await webClient.DownloadStringTaskAsync(uri);
    }
}
like image 36
Error404 Avatar answered Oct 15 '22 22:10

Error404