Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/300.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# HttpClient-任务已取消?_C#_Task Parallel Library_Dotnet Httpclient - Fatal编程技术网

C# HttpClient-任务已取消?

C# HttpClient-任务已取消?,c#,task-parallel-library,dotnet-httpclient,C#,Task Parallel Library,Dotnet Httpclient,当有一个或两个任务时,它可以正常工作,但是当我们列出了多个任务时,它会抛出一个错误“任务被取消” List<Task> allTasks = new List<Task>(); allTasks.Add(....); allTasks.Add(....); Task.WaitAll(allTasks.ToArray(), configuration.CancellationToken); private static Task<T> HttpClientS

当有一个或两个任务时,它可以正常工作,但是当我们列出了多个任务时,它会抛出一个错误“任务被取消”

List<Task> allTasks = new List<Task>();
allTasks.Add(....);
allTasks.Add(....);
Task.WaitAll(allTasks.ToArray(), configuration.CancellationToken);


private static Task<T> HttpClientSendAsync<T>(string url, object data, HttpMethod method, string contentType, CancellationToken token)
{
    HttpRequestMessage httpRequestMessage = new HttpRequestMessage(method, url);
    HttpClient httpClient = new HttpClient();
    httpClient.Timeout = new TimeSpan(Constants.TimeOut);

    if (data != null)
    {
        byte[] byteArray = Encoding.ASCII.GetBytes(Helper.ToJSON(data));
        MemoryStream memoryStream = new MemoryStream(byteArray);
        httpRequestMessage.Content = new StringContent(new StreamReader(memoryStream).ReadToEnd(), Encoding.UTF8, contentType);
    }

    return httpClient.SendAsync(httpRequestMessage).ContinueWith(task =>
    {
        var response = task.Result;
        return response.Content.ReadAsStringAsync().ContinueWith(stringTask =>
        {
            var json = stringTask.Result;
            return Helper.FromJSON<T>(json);
        });
    }).Unwrap();
}

List allTasks=new List();
所有任务。添加(…);
所有任务。添加(…);
Task.WaitAll(allTasks.ToArray(),configuration.CancellationToken);
私有静态任务HttpClientSendAsync(字符串url、对象数据、HttpMethod方法、字符串contentType、CancellationToken令牌)
{
HttpRequestMessage HttpRequestMessage=新的HttpRequestMessage(方法,url);
HttpClient HttpClient=新HttpClient();
httpClient.Timeout=新的时间跨度(常数.Timeout);
如果(数据!=null)
{
byte[]byteArray=Encoding.ASCII.GetBytes(Helper.ToJSON(data));
MemoryStream MemoryStream=新的MemoryStream(byteArray);
httpRequestMessage.Content=新的StringContent(新的StreamReader(memoryStream).ReadToEnd(),Encoding.UTF8,contentType);
}
返回httpClient.SendAsync(httpRequestMessage).ContinueWith(任务=>
{
var response=task.Result;
返回response.Content.ReadAsStringAsync().ContinueWith(stringTask=>
{
var json=stringTask.Result;
返回Helper.FromJSON(json);
});
}).Unwrap();
}

引发
TaskCanceledException
的原因可能有两个:

  • 在任务完成之前,与取消令牌关联的
    CancellationTokenSource
    上名为
    Cancel()
    的内容
  • 请求超时,即未在您在
    HttpClient.Timeout
    上指定的时间范围内完成
  • 我猜是暂停了。(如果是明确的取消,您可能已经知道了。)您可以通过检查异常更加确定:

    try
    {
        var response = task.Result;
    }
    catch (TaskCanceledException ex)
    {
        // Check ex.CancellationToken.IsCancellationRequested here.
        // If false, it's pretty safe to assume it was a timeout.
    }
    

    我遇到这个问题是因为我的
    Main()
    方法在返回之前没有等待任务完成,所以当我的控制台程序退出时,
    task myTask
    被取消

    #≥ 7.1 你可以继续等待任务

    公共静态异步任务Main(){ Task myTask=sendRequest();//创建任务的方式 HttpResponseMessage response=等待我的任务; //处理响应 } C#<7.1
    解决方案是在
    Main()
    (from)中调用
    myTask.GetAwaiter().GetResult()

    另一种可能是客户端不等待结果。如果调用堆栈上的任何一个方法没有使用wait关键字来等待调用完成,则可能会发生这种情况。

    另一个原因可能是,如果您正在运行服务(API)并在服务中放置断点(并且您的代码卡在某个断点处)(例如,Visual Studio解决方案显示调试而不是运行)。然后从客户端代码中点击API。因此,如果服务代码a在某个断点上暂停,您只需点击VS中的F5

    var clientHttp = new HttpClient();
    clientHttp.Timeout = TimeSpan.FromMinutes(30);
    
    以上是等待大型请求的最佳方法。 你对30分钟感到困惑;这是随机时间,你可以给任何你想要的时间

    换句话说,如果在30分钟之前得到结果,请求将不会等待30分钟。 30分钟表示请求处理时间为30分钟。
    当出现错误“任务被取消”或大数据请求要求时。

    在我的情况下,控制器方法不是异步的,控制器方法内部调用的方法是异步的


    因此,我想使用async/Wait一直到顶层是很重要的,以避免类似的问题。

    在我的.net core 3.1应用程序中,我遇到了两个问题,其内在原因是超时异常。 1,一个是我得到聚合异常,它的内部异常是超时异常 2、其他情况为任务取消异常

    我的解决办法是

    catch (Exception ex)
                {
                    if (ex.InnerException is TimeoutException)
                    {
                        ex = ex.InnerException;
                    }
                    else if (ex is TaskCanceledException)
                    {
                        if ((ex as TaskCanceledException).CancellationToken == null || (ex as TaskCanceledException).CancellationToken.IsCancellationRequested == false)
                        {
                            ex = new TimeoutException("Timeout occurred");
                        }
                    }                
                    Logger.Fatal(string.Format("Exception at calling {0} :{1}", url, ex.Message), ex);
                }
    

    我使用了一个简单的调用,而不是
    async
    。当我添加
    wait
    并使方法
    async
    时,它就开始正常工作了

    public async Task<T> ExecuteScalarAsync<T>(string query, object parameter = null, CommandType commandType = CommandType.Text) where T : IConvertible
            {
                using (IDbConnection db = new SqlConnection(_con))
                {
                    return await db.ExecuteScalarAsync<T>(query, parameter, null, null, commandType);
                }
            }
    
    公共异步任务ExecuteScalarAsync(字符串查询,对象参数=null,CommandType CommandType=CommandType.Text),其中T:IConvertible { 使用(IDbConnection db=newSQLConnection(_con)) { 返回wait db.ExecuteScalarAsync(查询,参数,null,null,commandType); } }
    将@JobaDiniz的评论升级为答案:

    不要做显而易见的事情并处理
    HttpClient
    实例,即使代码“看起来正确”:

    异步任务方法(){
    使用(var client=new HttpClient())
    返回client.GetAsync(请求);
    }
    
    C#的新RIAA语法也是如此;稍微不那么明显:

    异步任务方法(){
    使用var client=new HttpClient();
    返回client.GetAsync(请求);
    }
    

    相反,请为您的应用程序或库缓存
    HttpClient
    的静态实例,并重新使用它:

    statichttpclient=newhttpclient();
    异步任务方法(){
    返回client.GetAsync(请求);
    }
    

    (Async()请求方法。)

    内部异常说明了什么?为什么将
    CancellationToken
    作为参数而不使用它?我的原因是错误地处理
    HttpClient
    ,例如
    Async任务方法(){using(var client=new HttpClient())return client.GetAsync(request);}
    对于那些使用
    HttpClient
    的人,比如@JobaDiniz(使用
    using()
    ),请停止!原因:那么可能的解决方案是什么呢?我有一个类似的问题。@Dimi-这很旧,但我使用的解决方案是将Timeout属性设置为更大的值:
    HttpClient.Timeout=TimeSpan.FromMinutes(30)
    @RQDQ,你就是那个人,伙计!不使用构造函数为我解决了问题。在我的特定情况下,我想要一个以毫秒为单位的超时。使用
    TimeSpan.frommilless(Configuration.HttpTimeout)
    而不是
    new TimeSpan(Configuration.HttpTimeout)