使用带有 Http 触发器的取消令牌的 Azure 函数

Noo*_*der 9 c# multithreading azure cancellation-token azure-functions

我正在使用取消令牌在 Azure 中开发一个函数。它是一个 Http 触发器。

我在方法参数中传入了一个取消令牌。

其长运行功能。我在进程之间取消了请求,但进程继续运行并且取消令牌不生效。

这在 Azure Functions 中是否支持,如果我在两者之间取消 Http 请求,它也应该取消其执行,但事实并非如此。

我通过一小段代码对此进行了测试

public static class LongRunningFunction
    {
        [FunctionName("LongRunningFunction")]
        public static async Task<IActionResult> RunAsync(
            [HttpTrigger(AuthorizationLevel.Anonymous, "get", "post",  Route = "Long")]
            HttpRequest req, ILogger log, CancellationToken token)
        {
            try
            {
                await Task.Delay(10000, token);
                return new OkResult();

            }
            catch (OperationCanceledException)
            {
                return new NotFoundResult();
            }
            catch (Exception e)
            {
                return new InternalServerErrorResult();
            }
        }
    }
Run Code Online (Sandbox Code Playgroud)

我使用 Postman 执行。

难道我做错了什么?

我正在从以下链接获取帮助

Miq*_*Miq 8

我知道这是一个老问题,但我找到了这个问题的答案。

在 Azure Functions 中,有 2 个取消令牌。

在函数方法参数中传递的令牌是主机取消令牌 - 当主机即将关闭时请求取消。

另一个标志是req.HttpContext.RequestAborted财产。当浏览器取消请求时它被取消 - 这就是你所追求的。

此外,您可以使用以下代码:

using var cancellationSource = CancellationTokenSource.CreateLinkedTokenSource(hostCancellationToken, req.HttpContext.RequestAborted);
Run Code Online (Sandbox Code Playgroud)

获取在主机或请求被取消时取消的令牌。

  • 每当创建这样的链接 CancellationTokenSource 时,_总是_在完成后或创建泄漏时处置您创建的 CTS,因为长期存在的令牌(本例中为“hostCancellationToken”)将维护对您的 per- 的强引用。请求令牌源。 (2认同)

Thi*_*dio 1

如果不使用耐用功能,我认为这是不可能的。这是使用 Durable 的示例:

[FunctionName("ApprovalWorkflow")]
public static async Task Run(
    [OrchestrationTrigger] IDurableOrchestrationContext context)
{
    await context.CallActivityAsync("RequestApproval", null);
    using (var timeoutCts = new CancellationTokenSource())
    {
        DateTime dueTime = context.CurrentUtcDateTime.AddHours(72);
        Task durableTimeout = context.CreateTimer(dueTime, timeoutCts.Token);

        Task<bool> approvalEvent = context.WaitForExternalEvent<bool>("ApprovalEvent");
        if (approvalEvent == await Task.WhenAny(approvalEvent, durableTimeout))
        {
            timeoutCts.Cancel();
            await context.CallActivityAsync("ProcessApproval", approvalEvent.Result);
        }
        else
        {
            await context.CallActivityAsync("Escalate", null);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

https://learn.microsoft.com/en-us/azure/azure-functions/durable/durable-functions-overview?tabs=csharp# human