Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 带CancellationToken的异步/等待不';我不能取消手术_C#_Async Await_Cancellationtokensource - Fatal编程技术网

C# 带CancellationToken的异步/等待不';我不能取消手术

C# 带CancellationToken的异步/等待不';我不能取消手术,c#,async-await,cancellationtokensource,C#,Async Await,Cancellationtokensource,我想使用CancellationToken中止文件下载。这就是我所尝试的: public async Task retrieveDocument(Document document) { // do some preparation work first before retrieving the document (not shown here) if (cancelToken == null) { cancelToken = new Cancellat

我想使用
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;
}
似乎未更新
iscancellationrequest
。因此,操作没有取消。我也试着用这个

cancelToken.ThrowIfCancellationRequested();
try{
    documentResult = await Task.Run(() => manager.GetDocumentById (documentId), cancelToken);
} catch(TaskCanceledException){
    Console.WriteLine("task canceled here");
}
但一切都没有改变

我做错了什么

编辑:

以下是缺少的部分,如
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;
}

在启动GetDocumentSync方法后,您的代码只调用一次throwifcancellationrequest(),这使得捕获取消的窗口非常小

您需要将
CancellationToken
传递给GetDocumentById,并让它在操作之间调用
throwifccancellationrequested
,或者直接将令牌传递给较低级别的一些调用

作为对调用方法和取消令牌之间管道的快速测试,您可以将
getDocumentSync
更改为:

cancelToken.ThrowIfCancellationRequested();
documentResult = await Task.Run(() => manager.GetDocumentById(documentId));
cancelToken.ThrowIfCancellationRequested();
并在创建
cancelationtokensource
之后调用
CancelToken.CancelAfter(50)
或simlar。。。根据运行
GetDocumentById
所需的时间,您可能需要调整50的值

[编辑]

根据您对问题的编辑,最快的修复方法是将
CancelToken
向下传递到
WsGetResponseString
并使用
CancelToken.Register()
调用
WebRequest.Abort()


您还可以使用
CancelAfter()
来实现50秒超时,从
BeginGetResponse..EndGetResponse
切换到
GetResponseAsync
等。

启动GetDocumentAsync方法后,您的代码只调用
throwifccancellationRequested()
一次,使捕捉取消的窗口非常小

您需要将
CancellationToken
传递给GetDocumentById,并让它在操作之间调用
throwifccancellationrequested
,或者直接将令牌传递给较低级别的一些调用

作为对调用方法和取消令牌之间管道的快速测试,您可以将
getDocumentSync
更改为:

cancelToken.ThrowIfCancellationRequested();
documentResult = await Task.Run(() => manager.GetDocumentById(documentId));
cancelToken.ThrowIfCancellationRequested();
并在创建
cancelationtokensource
之后调用
CancelToken.CancelAfter(50)
或simlar。。。根据运行
GetDocumentById
所需的时间,您可能需要调整50的值

[编辑]

根据您对问题的编辑,最快的修复方法是将
CancelToken
向下传递到
WsGetResponseString
并使用
CancelToken.Register()
调用
WebRequest.Abort()

您还可以使用
CancelAfter()
来实现50秒超时,从
BeginGetResponse..EndGetResponse
切换到
GetResponseAsync

我想使用CancellationToken中止文件下载

下载文件是一种I/O操作,在.NET平台上可以使用异步可取消(基于I/O完成端口)功能。但你似乎没有使用它们

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

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

  • 使用
    HttpClient
  • Windows Phone
  • 使用
    WebClient
    :有自己的取消机制:方法,您可以使用令牌的方法将其连接到取消令牌: myToken.Register(myWebclient.CancelAsync)
  • 使用抽象WebRequest:如果它不是使用附加的取消令牌创建的,就像您编辑的示例一样,并且您实际上不是下载文件,而是读取内容字符串,则需要使用前面提到的几种方法的组合
您可以执行以下操作:

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());
    }
}
静态异步任务WsGetResponseString(WebRequest webreq、CancellationToken cancelToken)`
{
cancelToken.Register(webreq.Abort);
使用(var response=wait webReq.GetResponseAsync())
使用(var stream=response.GetResponseStream())
使用(var destStream=new MemoryStream())
{
wait stream.CopyToAsync(destStream,4096,cancelToken);
返回Encoding.UTF8.GetString(destStream.ToArray());
}
}
我想使用CancellationToken中止文件下载

下载文件是一种I/O操作,在.NET平台上可以使用异步可取消(基于I/O完成端口)功能。但你似乎没有使用它们

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

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

  • 使用
    HttpClient
  • Windows Phone
  • 使用
    WebClient
    :有自己的取消机制:方法,您可以使用令牌的方法将其连接到取消令牌: myToken.Register(myWebclient.CancelAsync)
  • 使用抽象WebRequest:如果它不是使用附加的取消令牌创建的,就像您编辑的示例一样,并且您实际上不是下载文件,而是读取内容字符串,则需要使用前面提到的几种方法的组合
您可以执行以下操作:

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());
    }
}
静态异步任务WsGetResponseString(WebRequest webreq、CancellationToken cancelToken)`
{
cancelToken.Register(webreq.Abort);
使用(var response=wait webR)