【问题标题】:Task method returns TaskCanceledException was caught任务方法返回 TaskCanceledException 被捕获
【发布时间】:2014-08-11 16:35:25
【问题描述】:

我正在尝试调用服务,该服务应该返回所有记录,但我收到 TaskCancelledException 并显示一条消息 A 任务已取消,然后结果为空。我知道有很多数据(尝试使用小数据并且工作正常)。我怎样才能让它继续工作(保持抓取记录)而不抛出“A Task was cancelled”。这是我的方法

public async Task<ActionResult<string>> ObtainData(string url, CancellationToken ct = default(CancellationToken))
{            
    Result<string> result = new Result<string>();
    try
    {
        HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, url);
        HttpResponseMessage response = await httpClient.SendAsync(request); //HttpClient

        string jsonresult = await HandleReceipt(response, type);

        result.Result = jsonresult;
    }
    catch (Exception ex)
    {
        result.Message = "Problem obtaining data.";
    }

    return result;
}

我看到有一个取消令牌正在传递,有没有办法处理取消?另外,这个方法是从这里调用的:

public async void GetJsonData()
{
    string json = await ObtainData();
}

我希望它在不取消的情况下完成获取请求。

【问题讨论】:

  • 请求是否需要时间才能完成?
  • 是的,它可以很好地处理请求的小数据集。但不止于此,它给了我“任务已取消”
  • 在完成此操作时,我还必须在视图中添加诸如“加载”之类的内容..但这就像它的第一部分。
  • 您似乎没有使用 Cancellation 令牌,来自方法存根,我猜这是您未从 SendAsync 声明的另一个?显示异常的堆栈跟踪。

标签: c# wpf async-await


【解决方案1】:

从您的问题和 cmets 看来,您的请求已超时。尝试设置HttpClient.Timeout 属性

public async Task<ActionResult<string>> ObtainData(string url, CancellationToken ct = default(CancellationToken))
{            
   Result<string> result = new Result<string>();
   try
   {
       var request = (HttpWebRequest) WebRequest.Create(url);
       request.Method = "GET";
       HttpResponseMessage response = await httpClient.SendAsync(request); //HttpClient
       httpClient.TimeOut = TimeSpan.MaxValue // change this as you like

       string jsonresult = await HandleReceipt(response, type);

       result.Result = jsonresult;
   } 
   catch (Exception ex)
   {
      result.Message = "Problem obtaining data.";
   }

   return result;
}

编辑

关于您对异常的评论,这是来自 MSDN:

必须在调用 GetRequestStream 或 GetResponse 方法之前设置 Timeout 属性。

在发出请求之前创建HttpClient 的新实例,或者在初始化客户端的代码中设置它(我假设是构造函数)。

【讨论】:

  • 谢谢 Yuval,我添加了那行,但是它说“这个实例已经启动了一个或多个请求。只能在发送第一个请求之前修改属性。”,我也移动了上面的行请求。但仍然得到同样的错误。我认为 httpclient 正在被 ping 服务或类似的东西使用..所以它会在某处发送一个取消令牌..有没有办法检查这个?
  • 尝试设置HttpClient 的新实例:var client = new HttpClient 并使用它来提出您的请求
  • @ergwin 注意我编辑了 HttpWebRequest 的创建,因为我看到使用 new HttpWebRequest 已过时。
【解决方案2】:

正如 Yuval Itzchakov 提到的,您应该将 Timeout 属性设置为更大的值(但它是 TimeSpan 而不是整数),并且如果您使用异步模式,则应该在 HTTP 请求调用中使用取消标记。 并且没有必要使用全局 HttpClient(正如 Yuval 指出的那样),尤其是在这种调用噩梦的繁重异步方法中(此外,我不明白为什么应该在获取数据异步中调用任何东西的原因)。

    public async Task<ActionResult<string>> ObtainData(string url, CancellationToken ct = default(CancellationToken))
    {
        try
        {
            using (var httpClient = new HttpClient
            {
                Timeout = TimeSpan.MaxValue
            })
            {
                using (var request = new HttpRequestMessage(HttpMethod.Get, url))
                {
                    using (var response = await httpClient.SendAsync(request, ct))
                    {
                        return new ActionResult<string>()
                        {
                            Result = await HandleReceipt(response, type)
                        };
                    }
                }
            }
        }
        catch (Exception ex)
        {
            return new ActionResult<string>
            {
                Message = "Problem obtaining data. " + ex
            };
        }
    }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-10-15
    • 1970-01-01
    • 1970-01-01
    • 2016-03-06
    • 2018-08-06
    • 1970-01-01
    • 1970-01-01
    • 2011-08-27
    相关资源
    最近更新 更多