Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/289.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# Web API 2-全局异常处理程序无法处理TaskCancellation_C#_Asp.net Web Api_Async Await - Fatal编程技术网

C# Web API 2-全局异常处理程序无法处理TaskCancellation

C# Web API 2-全局异常处理程序无法处理TaskCancellation,c#,asp.net-web-api,async-await,C#,Asp.net Web Api,Async Await,用于演示问题的代码: 假设测试是一个真实的实现,比如DB调用 结果表明,未经处理的异常将被捕获到允许您处理它们的全局处理程序中 如果我用ExceptionFilter替换MyErrorHandler,这确实有效,但我正在使用的代码库使用处理程序除外,因为错误逻辑是一个横切问题,无论错误来自何处,都是相同的 如果引发的异常类型不是TaskCancelledException,则会按预期调用处理程序 我也尝试过最新版本的Web API(5.2.3) 唯一的解决办法是在可能引发这种类型异常的所有地方

用于演示问题的代码:

  • 假设测试是一个真实的实现,比如DB调用
  • 结果表明,未经处理的异常将被捕获到允许您处理它们的全局处理程序中
  • 如果我用ExceptionFilter替换MyErrorHandler,这确实有效,但我正在使用的代码库使用处理程序除外,因为错误逻辑是一个横切问题,无论错误来自何处,都是相同的
  • 如果引发的异常类型不是TaskCancelledException,则会按预期调用处理程序
  • 我也尝试过最新版本的Web API(5.2.3)
  • 唯一的解决办法是在可能引发这种类型异常的所有地方添加try/catch块,不用说这很痛苦,我希望避免使用处理程序
我讨厌称这是一个错误,因为这不是我的代码,但经过几个小时的尝试,它开始有这种感觉

using System;
using System.Net;
using System.Threading;
using System.Threading.Tasks;
using System.Web.Http;
using System.Web.Http.ExceptionHandling;

namespace WebApplication3.Controllers
{
    public class TestController : ApiController
    {
        public async Task<string> Get()
        {
            var cancellationTokenSource = new CancellationTokenSource(TimeSpan.FromSeconds(1));
            return await new TestThing().ExecuteAsync(cancellationTokenSource.Token);
        }
    }

    public class MyErrorHandler : ExceptionHandler
    {
        public override Task HandleAsync(ExceptionHandlerContext context, CancellationToken cancellationToken)
        {
            throw new HttpResponseException(HttpStatusCode.InternalServerError);
        }
    }


    public class TestThing
    {
        public async Task<string> ExecuteAsync(CancellationToken cancellationToken)
        {
            // Remove this to see the problem, I don't want to add these
            // try/catch statements all over the codebase.
            try
            {
                await Task.Delay(TimeSpan.FromMinutes(1), cancellationToken);
            }
            catch (Exception ex)
            {
                throw new Exception("Failure...");
            }

            return await Task.FromResult("Testing...");
        }
    }
}
使用系统;
Net系统;
使用系统线程;
使用System.Threading.Tasks;
使用System.Web.Http;
使用System.Web.Http.ExceptionHandling;
命名空间WebApplication3.Controllers
{
公共类TestController:ApicController
{
公共异步任务Get()
{
var cancellationTokenSource=新的cancellationTokenSource(TimeSpan.FromSeconds(1));
return wait new TestThing().ExecuteAsync(cancellationTokenSource.Token);
}
}
公共类MyErrorHandler:ExceptionHandler
{
公共覆盖任务HandleAsync(例外HandlerContext上下文,CancellationToken CancellationToken)
{
抛出新的HttpResponseException(HttpStatusCode.InternalServerError);
}
}
公共类测试
{
公共异步任务ExecuteAsync(CancellationToken CancellationToken)
{
//删除此项以查看问题,我不想添加这些
//代码库中的try/catch语句。
尝试
{
等待任务延迟(TimeSpan.FromMinutes(1),cancellationToken);
}
捕获(例外情况除外)
{
抛出新异常(“失败…”);
}
返回等待任务。FromResult(“测试…”);
}
}
}

由于缺乏建议或答案,我选择了一个定制的消息处理程序

    public class AsyncFixHandler : DelegatingHandler
    {
        protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
        {
            try
            {
                return await base.SendAsync(request, cancellationToken);
            }
            catch (TaskCanceledException)
            {
                // TODO: Log the issue here
                return new HttpResponseMessage(HttpStatusCode.InternalServerError);
            }
        }
    }
公共类AsyncFixHandler:DelegatingHandler
{
受保护的覆盖异步任务SendAsync(HttpRequestMessage请求,CancellationToken CancellationToken)
{
尝试
{
返回wait base.sendaync(请求、取消令牌);
}
捕获(TaskCanceledException)
{
//TODO:在此处记录问题
返回新的HttpResponseMessage(HttpStatusCode.InternalServerError);
}
}
}

这并不理想,但尝试/捕获是在一个地方。我正在成功地将其用作解决方案,直到出现更好的解决方案。

这似乎是一个老问题,而且仍有一些人报告问题。我建议您在ASP.NET回购中创建一个问题,并使用您的解决方法或暂时解决。

这有帮助吗?感谢您提供的bug报告链接,在我多次尝试解决/研究这一问题时,我从未发现这一点。不过,我可以在5.2.3中确认这仍然是一个问题:(感谢此解决方案。对于像我这样希望启用全局异常处理程序和记录器的其他人,只需抛出一个新的替换异常,而不是返回HttpResponseMessage