Я хочу использовать CancellationToken
, чтобы прервать загрузку файла. Это то, что я пробовал:Async/wait with CancellationToken не отменяет операцию
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 затем следует использовать для отмены операции:
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
не обновляется. Таким образом, операция не отменяется. Я также попытался использовать это
cancelToken.ThrowIfCancellationRequested();
try{
documentResult = await Task.Run(() => manager.GetDocumentById (documentId), cancelToken);
} catch(TaskCanceledException){
Console.WriteLine("task canceled here");
}
но ничего не изменилось.
Что я делаю неправильно?
Edit:
Вот недостающие части, как 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;
}
Я не очень понимаю, что вы пытаетесь сделать. Вы вызываете ThrowIfCancellationRequested * перед тем, как вы начинаете выполнять работу, которая вряд ли что-либо сделает. Вам необходимо периодически вызывать его внутри кода, который заставляет работу работать. Например, внутри цикла. – svinja
Я не мог воспроизвести проблему при использовании 'Task.Delay' вместо' webservice.GetDocumentAsync'. Так что, возможно, этот служебный вызов или следующий код ('do some other stuff') не полностью поддерживают совместную отмену задачи. – Dirk
Что делает 'GetDocumentById'? Если вы отмените токен после запуска GetDocumentById, никто не заметит, так как он не контролируется. –