Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/asp.net-core/3.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# Asp.net核心中间件,用于在需要很长时间时取消请求_C#_Asp.net Core_Asp.net Core 2.1 - Fatal编程技术网

C# Asp.net核心中间件,用于在需要很长时间时取消请求

C# Asp.net核心中间件,用于在需要很长时间时取消请求,c#,asp.net-core,asp.net-core-2.1,C#,Asp.net Core,Asp.net Core 2.1,如果我的api花费的时间超过x,我需要一个中间件来取消请求。 我的所有api调用都是异步且可取消的: public async Task<IActionResult> Get(CancellationToken token) { } ... public async Task InvokeAsync(HttpContext context) { //.... int customDurationMilis = 1000; //1second canc

如果我的api花费的时间超过x,我需要一个中间件来取消请求。 我的所有api调用都是异步且可取消的:

public async Task<IActionResult> Get(CancellationToken token) {  }

... 

public async Task InvokeAsync(HttpContext context)
{
    //....
    int customDurationMilis = 1000; //1second

    cancellTimer = new Timer(CancellRequestCallBack, context, customDurationMilis, Timeout.Infinite);
    //...

    await _next(context);
}

private void CancellRequestCallBack(HttpContext context)
{
    //log...
    //Aborts the connection underlying this request.
    context.Abort();
}
至少有了这一点,我在errorhandlermiddleware中捕捉到了返回状态代码500的异常。但我不知道;邮递员收不到。相反,我得到了 “无法获得任何响应”
另外,我想带有请求的线程仍将运行。

如何使用添加弹性和瞬时故障处理


Polly是一个.NET弹性和瞬时故障处理库,允许开发人员以流畅和线程安全的方式表达策略,如重试、断路器、超时、隔离和回退。

如何使用添加弹性和瞬时故障处理


Polly是一个.NET弹性和瞬时故障处理库,允许开发人员以流畅和线程安全的方式表达策略,如重试、断路器、超时、隔离和回退。

这实际上很难实现,原因有两个:

  • 取消是合作的。这意味着您需要等待(传递)的所有内容来尊重令牌
  • 异步意味着没有要中止的线程。您可以中止整个TCP连接,但是如果没有人在侦听令牌,也没有人在读取主体,那么它不会对正在运行的服务器代码做任何事情
  • 使用
    Task.WhenAny
    不是一个好的解决方案,因为您可能会同时使用
    HttpContext
    。您“取消”的代码可能会在中间件尝试写入超时响应的同时写入有效响应。即使抛出异常,也很危险,因为有其他正在运行的代码可能会同时触及
    HttpContext
你可以冒险,但可能有微妙的种族条件导致事情以意想不到的方式失败


如果您正在考虑取消令牌,那么您可以取消令牌并等待下一个解卷。当它启动时,您可以在写入之前查看响应是否已启动,并返回408(请求超时)。

这实际上很难实现,原因有两个:

  • 取消是合作的。这意味着您需要等待(传递)的所有内容来尊重令牌
  • 异步意味着没有要中止的线程。您可以中止整个TCP连接,但是如果没有人在侦听令牌,也没有人在读取主体,那么它不会对正在运行的服务器代码做任何事情
  • 使用
    Task.WhenAny
    不是一个好的解决方案,因为您可能会同时使用
    HttpContext
    。您“取消”的代码可能会在中间件尝试写入超时响应的同时写入有效响应。即使抛出异常,也很危险,因为有其他正在运行的代码可能会同时触及
    HttpContext
你可以冒险,但可能有微妙的种族条件导致事情以意想不到的方式失败


如果您正在考虑取消令牌,那么您可以取消令牌并等待下一个解卷。当它这样做时,您可以在写入之前查看响应是否已启动,并返回408(请求超时)。

提出了一个关于令牌的解决方案。 其思想是创建一个新令牌并为其定义一个超时。 但是,还需要使用CreateLinkedTokenSource将原始令牌与新令牌链接起来

public async Task InvokeAsync(HttpContext context)
{
    using (var timoutTS = CancellationTokenSource.CreateLinkedTokenSource(context.RequestAborted))
    {
        timoutTS.CancelAfter(200);
        context.RequestAborted = timoutTS.Token;
        await _next(context);
    }
}

提出了一个关于代币的解决方案。 其思想是创建一个新令牌并为其定义一个超时。 但是,还需要使用CreateLinkedTokenSource将原始令牌与新令牌链接起来

public async Task InvokeAsync(HttpContext context)
{
    using (var timoutTS = CancellationTokenSource.CreateLinkedTokenSource(context.RequestAborted))
    {
        timoutTS.CancelAfter(200);
        context.RequestAborted = timoutTS.Token;
        await _next(context);
    }
}

谢谢John,我们知道如何在自定义中间件组件中实现它。我在最初的问题中添加了一个更新。谢谢John,我们知道如何在自定义中间件组件中进行更新。我在最初的问题中添加了一个更新。谢谢@davidfoll。创建新令牌并使用CancelAfter()为其设置超时并将其链接到原始令牌(下面的新答案)将不起作用?您好,这是针对
netcore 2.1
netcore v3.1的任何更新或合适的解决方案而询问和回答的。创建新令牌并使用CancelAfter()为其设置超时并将其链接到原始令牌(下面的新答案)将不起作用?您好,这是针对
netcore 2.1
任何更新或适用于
netcore v3.1