2012-12-10 22 views
9

我創建了一個示例示例來使用WebClient使用異步和等待方法調用鏈接現在我想附加取消異步調用功能也。但是我無法獲取CancellationTokenSource標記並將DownloadStringTaskAsync附加到此取消標記。以下是我的代碼可以告訴我如何做到這一點。如何將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調用。爲什麼取消按鈕無法取消異步呼叫?

+0

你不以任何方式使用'CancellationTokeSource',怎麼是'WebClient'應該知道它應該取消時,你不告訴它? – svick

+0

謝謝你的回覆。但我試圖將該標記作爲DownloadStringTaskAsync方法的參數傳遞,但是對於支持它的此方法沒有重載。因此,我沒有得到如何使用DownloadStringTaskAsync方法取消令牌。你可以建議我一些好書,閱讀C#中的所有這些新的更新與TAP功能。 –

回答

14

WebClient的異步功能早於.Net 4.5,因此它僅部分支持the Task-based Asynchronous Pattern。這包括擁有自己的取消機制:the CancelAsync() method,即使使用新的-TaskAsync方法也可以使用。調用此方法時,CancellationToken被取消,您可以使用its Register() method

cts.Token.Register(wc.CancelAsync); 

作爲替代方案,你可以使用新的HttpClient,斯蒂芬建議,並全面支持TAP,包括CancellationToken秒。基於svick的回答

3

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線將實際完成同步。

0

擴展方法:

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

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