如何CancellationTokenSource重视DownloadStringTaskAsync

2019-08-03 18:46发布

我的创建示例例如调用链接使用异步使用Web客户端,现在等待的方法我要附加取消异步调用的功能也。 但我不能够得到CancellationTokenSource令牌和附加DownloadStringTaskAsync该取消标记。 以下是我的代码谁能告诉我如何做到这一点。

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.");
        }

当我的取消按钮调用cts.Cancel的DownloadStringTaskAsync呼叫没有取消。 为什么取消按钮无法取消异步调用?

Answer 1:

的异步能力WebClient早.NET 4.5,所以它支持的基于任务的异步模式仅部分。 这包括具有其自身的消除机制: 在CancelAsync()方法 ,甚至与新的工作-TaskAsync方法。 调用此方法时CancellationToken被取消,你可以用它Register()方法 :

cts.Token.Register(wc.CancelAsync);

作为替代方案,你可以使用新HttpClient ,斯蒂芬建议,并全面支持TAP,包括CancellationToken秒。



Answer 2:

WebClient不支持取消。 我建议你使用一个新的类型,如HttpClient

...
cts = new CancellationTokenSource();
string result;
using (var client = new HttpClient())
using (var response = await client.GetAsync("http://gyorgybalassy.wordpress.com", cts.Token))
{
  result = await response.Content.ReadAsStringAsync();
}

if (result.Length < 100000)
...

GetAsync方法在默认情况下将不完整的,直到它读取整个响应,所以await response.Content.ReadAsStringAsync行会实际上同步完成。



Answer 3:

基于svick的回答扩展方法:

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);
    }
}


文章来源: How to attach CancellationTokenSource to DownloadStringTaskAsync method and cancel the async call?