我正在ASP.NET中实现一个REST API端点,它应该执行以下操作:

  1. 异步启动长时间运行的算法
  2. 启动算法后立即接受返回202(无等待)

这就是端点的样子:

app.MapPut(
    "/api/instance/{id}",
    (int id, InstanceDto instanceDto, IInstanceRunningService service) =>
    {
        // Start the execution asynchronously and return ASAP
        service.RunInstance(instanceDto);
        return TypedResults.Accepted($"/api/instance/{id}");
    })

服务中的RunInstance方法就是这样的:

public async Task RunInstance(InstanceDto instanceDto)
{
    // Asynchronously call another API that we are starting the execution of the algorithm
    // We do not need to wait for the response, we just want to start the algorithm ASAP (again no await)
    _ = this.AnotherApiClient.PutAsync(instanceDto);

    // 计算算法 and await the result
    var result = await 算法rithm.Run(instanceDto.Parameters);
    
    // Finally call the other API again to notify that the computation finished
    await this.AnotherApiClient.PutAsync(instanceDto);
}

我想要实现的操作顺序是:

  1. 返回202接受
  2. 通知另一个API计算正在开始(我们不关心这个API调用如何结束,因为我们将在步骤4中发送另一个.
  3. 计算算法
  4. 通知另一个API计算已完成

我想不出实现这一点的最好方法.有太多的 Select :

  • service.RunInstance(instanceDto);
  • service.RunInstance(instanceDto).Start();
  • Task.Run(() => service.RunInstance(instanceDto))
  • 将RunInstance设置为异步委托并执行delegate.BeginInvoke()
  • 创建Thread或使用ThreadPool
  • 也许用更多的rectc方法实现不同的服务,

推荐答案

我想不出最好的方法来实现这一点.有这么多的 Select :

我认为没有一个是"最好的".这种任务的常用方法是使用某种背景处理."简单"的一个是使用内置的hosted services,特别是判断出Queued background tasks选项(您可以实例化几个"处理器"来处理同一队列—例如参见this answer).

此外,不要将已解析的依赖项(即IInstanceRunningService service)传递给您的处理程序任务/队列,因为它们的生存期由原始请求的生存期控制,一次性服务将与其一起处置,手动创建作用域并从中解决所需的一切-例如,参见文档的第Consuming a scoped service in a background task节.

或者,您可以考虑使用更高级的调度器,如HangfireQuartz和/或利用队列/服务总线的异步处理.

Csharp相关问答推荐

利用.NET 8中的AddStandardResilienceDeliveries和AddStandardHedgingDeliveries实现Resiliency

EF Core判断是否应用了AsSplitQuery()

C#相同名称的枚举方法和normal方法,参数类型不同

并行令牌更新

如何使用CsvReader获取给定列索引的列标题?

Microsoft. VisualBasic. FileIO. FileSystem. MoveFile()对话框有错误?

当我使用NET6作为目标框架时,为什么DotNet使用NET8作为MS包?

如何修改中间件或其注册以正确使用作用域服务?

如何使用XmlSerializer反序列化字符串数组?

REST API端点中异步后台代码执行的类型

Nuget包Serilog.Sinks.AwsCloudwatch引发TypeLoadExceptions,因为父类型是密封的

.NET 6控制台应用程序,RabbitMQ消费不工作时,它的程序文件中的S

在try 使用访问服务器上的文件夹时,如何解决CORS错误.NET核心API

关于扩展文件类C#的矛盾

为什么C#/MSBuild会自发地为不同的项目使用不同的输出路径?

使用SQL Server 2022+时,我是否必须将代码从SqlConnection类对象中迁移出来?

C#-如何将int引用获取到byte[]

最小API定义的Swagger标头参数

自定义ConsoleForMatter中的DI/Http上下文

不寻常的C#语法