使用CancellationToken进行异步/等待不会取消操作

编程入门 行业动态 更新时间:2024-10-26 00:32:27
本文介绍了使用CancellationToken进行异步/等待不会取消操作的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述

我想使用 CancellationToken 中止文件下载.这是我尝试过的:

I want to use the CancellationToken to abort a file download. This is what I tried:

public async Task retrieveDocument(Document document) { // do some preparation work first before retrieving the document (not shown here) if (cancelToken == null) { cancelToken = new CancellationTokenSource(); try { Document documentResult = await webservice.GetDocumentAsync(document.Id, cancelToken.Token); // do some other stuff (checks ...) } catch (OperationCanceledException) { Console.WriteLine("abort download"); } finally { cancelToken = null; } } else { cancelToken.Cancel(); cancelToken = null; } } public async Task<Document> GetDocumentAsync(string documentId, CancellationToken cancelToken) { Document documentResult = new Document(); try { cancelToken.ThrowIfCancellationRequested(); documentResult = await Task.Run(() => manager.GetDocumentById(documentId)); } return documentResult; }

cancelToken 然后应用于取消操作:

The cancelToken should then be used to cancel the operation:

public override void DidReceiveMemoryWarning () { // Releases the view if it doesn't have a superview. base.DidReceiveMemoryWarning (); if (cancelToken != null) { Console.WriteLine ("Token cancelled"); cancelToken.Cancel (); } }

似乎 IsCancellationRequested 没有更新.因此操作不会被取消.我也试图用这个

It seems that IsCancellationRequested is not updated. So the operation is not cancelled. I also tried to use this

cancelToken.ThrowIfCancellationRequested(); try{ documentResult = await Task.Run(() => manager.GetDocumentById (documentId), cancelToken); } catch(TaskCanceledException){ Console.WriteLine("task canceled here"); }

但没有任何改变.

我做错了什么?

以下是缺少的部分,例如 GetDocumentById :

Here are the missing parts like GetDocumentById:

public Document GetDocumentById(string docid) { GetDocumentByIdResult res; try { res = ws.CallGetDocumentById(session, docid); } catch (WebException e) { throw new NoResponseFromServerException(e.Message); } return res; } public Document CallGetDocumentById(Session session, string parmsstring) { XmlDocument soapEnvelope = Factory.GetGetDocumentById(parmsstring); HttpWebRequest webRequest = CreateWebRequest(session); webRequest = InsertEnvelope(soapEnvelope, webRequest); string result = WsGetResponseString(webRequest); return ParseDocument(result); } static string WsGetResponseString(WebRequest webreq) { string soapResult = ""; IAsyncResult asyncResult = webreq.BeginGetResponse(null, null); if (asyncResult.AsyncWaitHandle.WaitOne(50000)) { using (WebResponse webResponse = webreq.EndGetResponse(asyncResult)) { if (webResponse != null) { using (var rd = new StreamReader(webResponse.GetResponseStream())) { soapResult = rd.ReadToEnd(); } } } } else { webreq.Abort(); throw new NoResponseFromServerException(); } return soapResult; }

推荐答案

我想使用CancellationToken中止文件下载

I want to use the CancellationToken to abort a file download

下载文件是一项I/O操作,.NET平台上提供了异步可取消(基于I/O完成端口)功能.但是您似乎并没有使用它们.

Downloading a file is an I/O operation, for which asynchronous cancelable (I/O completion port based) functions are available on the .NET platform. Yet you seem to not be using them.

相反,您似乎正在使用 Task.Run 创建(一系列)任务,这些任务执行阻止I/O,其中取消令牌没有传递给 Task中的每个任务.运行链.

Instead you appear to be creating (a chain of) tasks using Task.Run that perform blocking I/O, where a cancelation token is not passed on to each task in your Task.Run chain.

有关进行异步,可等待和可取消的文件下载的示例,请参阅:

For examples of doing async, awaitable and cancelable file downloads, refer to:

  • 使用 HttpClient :如何异步复制并取消HttpContent?
  • Windows Phone :在Windows Phone 8中下载并保存异步文件
  • 使用 WebClient :具有自己的取消机制: CancelAsync 方法,您可以使用令牌的注册方法:
  • Using HttpClient: How to copy HttpContent async and cancelable?
  • Windows Phone: Downloading and saving a file Async in Windows Phone 8
  • Using WebClient: Has its own cancellation mechanism: the CancelAsync method, you can connect it to your cancellation token, using the token's Register method:
myToken.Register(myWebclient.CancelAsync);

  • 使用抽象的WebRequest :如果它不是使用附加的取消令牌创建的,就像您编辑的示例一样,并且您实际上并没有下载文件,而是在阅读内容字符串,则需要结合使用前面提到的几种方法.
  • Using the abstract WebRequest: If it was not created using an attached cancelation token, as seems to be the case for your edited example, and you are not actually downloading a file, but reading a content string, you need to use a combination of a few of the earlier mentioned methods.
  • 您可以执行以下操作:

    static async Task<string> WsGetResponseString(WebRequest webreq, CancellationToken cancelToken)` { cancelToken.Register(webreq.Abort); using (var response = await webReq.GetResponseAsync()) using (var stream = response.GetResponseStream()) using (var destStream = new MemoryStream()) { await stream.CopyToAsync(destStream, 4096, cancelToken); return Encoding.UTF8.GetString(destStream.ToArray()); } }

    更多推荐

    使用CancellationToken进行异步/等待不会取消操作

    本文发布于:2023-11-12 21:44:00,感谢您对本站的认可!
    本文链接:https://www.elefans.com/category/jswz/34/1582605.html
    版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
    本文标签:操作   CancellationToken

    发布评论

    评论列表 (有 0 条评论)
    草根站长

    >www.elefans.com

    编程频道|电子爱好者 - 技术资讯及电子产品介绍!