【问题标题】:system.threading.tasks.taskcanceledexception a task was canceled exceptionsystem.threading.tasks.taskcancelexception 任务被取消异常
【发布时间】:2022-02-17 02:53:43
【问题描述】:

我从 API 获取大量数据的代码是这样的

public static async Task<model> GetDataAsyncs(string url)
    {
        // Initialization.  
        mymodel responseObj = new mymodel();

        using (var httpClientHandler = new HttpClientHandler())
        {
            httpClientHandler.ServerCertificateCustomValidationCallback = (message, cert, chain, errors) => { return true; };
            using (var client = new HttpClient(httpClientHandler))
            {
                // Setting Base address.  
                client.BaseAddress = new Uri(apiBasicUri);

                // Setting content type.                   
                client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

                // Initialization.  
                HttpResponseMessage response = new HttpResponseMessage();

                // HTTP Get  
                response = await client.GetAsync(url ).ConfigureAwait(false);

                // Verification  
                if (response.IsSuccessStatusCode)
                {
                    // Reading Response.  
                    string result = response.Content.ReadAsStringAsync().Result;
                    responseObj.Status = true;
                    responseObj.Data = result;
                }
            }
        }


        return responseObj;
    }

我在我的控制器中调用上面的函数

public ActionResult myActionMethod()
        {
            string res= helper.GetDataAsync("url").Result.Data;
        }

有时这会引发错误 system.threading.tasks.taskcanceledexception a task was canceled 。这不会每次都发生。谁能指出我在这里做错了什么?

【问题讨论】:

  • 当客户端(浏览器)取消请求时(例如在浏览器中点击“停止”按钮),服务器将通过抛出TaskCanceledException来停止处理请求。这可能是正在发生的事情吗?
  • @GabrielLuci 不,页面开始加载后没有用户操作

标签: c# asp.net-mvc async-await


【解决方案1】:

我不能确定为什么会发生这种情况,但您的代码中有一些危险信号可以清理并可能解决此问题。

首先是你使用.ConfigureAwait(false)。它可能会导致一些意想不到的后果,所以我建议你不要使用它。我在an article I recently wrote 中谈论它。

其次,尽可能使用await 而不是.Result,这几乎总是如此。使用.Result 也会导致意想不到的、难以调试的后果。在您的代码中,我认为您没有理由不能使用 await

第三,the documentation of HttpClient 说:

HttpClient 旨在被实例化一次并在应用程序的整个生命周期中重复使用。为每个请求实例化一个 HttpClient 类将耗尽重负载下可用的套接字数量。这将导致 SocketException 错误。

因此您可以声明一个静态 HttpClient 并在每次需要时重复使用它。

第四,不需要这行:

HttpResponseMessage response = new HttpResponseMessage();

您在此处实例化一个新的HttpResponseMessage,但随后在下一行立即覆盖它。

进行这些更改后,您的代码可能如下所示:

private static HttpClient _client = new HttpClient(
    new HttpClientHandler {ServerCertificateCustomValidationCallback = (message, cert, chain, errors) => { return true; }}
) {
    BaseAddress = new Uri(apiBasicUri),
    DefaultRequestHeaders = {
        Accept = { new MediaTypeWithQualityHeaderValue("application/json") }
    }
};

public static async Task<model> GetDataAsyncs(string url)
{
    mymodel responseObj = new mymodel();

    var response = await _client.GetAsync(url);

    if (response.IsSuccessStatusCode)
    {
        var result = await response.Content.ReadAsStringAsync();
        responseObj.Status = true;
        responseObj.Data = result;
    }
    
    return responseObj;
}

然后将您的控制器操作更改为async 并使用await

public async Task<ActionResult> myActionMethod()
{
    var res = (await helper.GetDataAsync("url")).Data;
}

查看在进行这些更改后是否仍会出现异常。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-05-12
    • 2017-09-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多