【问题标题】:.NET Correct Task use.NET 正确任务使用
【发布时间】:2020-04-06 06:20:21
【问题描述】:

我是 .NET 任务和异步编码的新手,所以我想知道在我的情况下我应该做什么:

我有一个接收 XML 文件的 .NET Core WebApi,它充当以下过程的触发器:

  1. 我需要进程在“后台”运行,所以我的意思是 API 调用者应该立即得到响应,然后进程应该运行
  2. 我需要将 XML 解析为一个对象
  3. 有了这些数据,我需要联系 3 个 API
  4. 如果这些 API 中的任何一个没有响应或未能检索到所需的数据,我们需要停止并记录此情况
  5. 如果检索到所有数据,我需要对这些数据进行计算(从数据库中获取一些数据并使用 API 和数据库数据进行计算)
  6. 计算完成后,我需要发送电子邮件并联系另一个 API

    7.最重要的是:由于 AppRecycle,我对此是否安全?

这只是为了解释我的情况,所以我有以下内容:

[HttpPost]
public async Task<JsonResult> DepositAsync([FromBody] Taa message){
try
{
    Api1Response api1Response = await this.GetApiData1();
    Api1Response api2Response = await this.GetApiData2();

    // If all of this was successful, do the calculation
    CalculationResult result = await this.CalculateAsync(api1Response, api2Response);

    // Notify 
    await Notify(result);
}
catch (Exception ex)
{
    Log.Error($"Something went wrong: {ex.Message}", ex);
    throw;
}


return new JsonResult(new ApiResponse<string>(requestId.ToString(), Response, StatusCodes.Status200OK) { Data = "Success" });
}

我现在的问题:

  1. 什么时候需要使用 Task.Run(() => {});在GetApiData1()、GetApiData2()方法里面,做Http调用?
  2. 我需要在 Task.Run(() => {}) 中调用 GetApi 方法吗? ?
  3. 一般来说,什么时候需要使用Task.Run,​​什么时候不需要?

或者我只需要这样做:

[HttpPost]
public async Task<JsonResult> DepositAsync([FromBody] Taa message){
try
{
    Task.Run(() => {
        Api1Response api1Response = await this.GetApiData1();
        Api1Response api2Response = await this.GetApiData2();

        // If all of this was successful, do the calculation
        CalculationResult result = await this.CalculateAsync(api1Response, api2Response);

        // Notify 
        await Notify(result);
    });  
}
catch (Exception ex)
{
    Log.Error($"Something went wrong: {ex.Message}", ex);
    throw;
}


return new JsonResult(new ApiResponse<string>(requestId.ToString(), Response, StatusCodes.Status200OK) { Data = "Success" });
}

非常感谢!

【问题讨论】:

    标签: .net asp.net-core asynchronous task-parallel-library


    【解决方案1】:

    您可以在不使用await 的情况下使用Task.Run 将一些工作从ThreadPool“卸载”到另一个线程,这是正确的。这样做时,您的请求的响应时间不会受到其中完成的工作的影响。

    但是,该函数内部发生的任何异常都不会被抛出到 caller 线程(因为不等待调用)。这实际上意味着您的 try-catch 块将仅捕获在创建新的 Task 时发生的异常(通过 Task.Run 方法)。换句话说,它不会捕获在处理传递给 Task.Run 方法的 lambda 时发生的任何错误。

    因此,在您的情况下,第二种方法是正确的(上面提到了缺点)。 此外,IIS 将等待正在运行的线程完成并退出在回收时,受线程池上设置的超时限制。因此,如果执行大于超时,线程将被强制终止。

    最后,在 .Net Core 中引入了新的服务类型,它们被称为托管服务并实现了IHostedService。它们旨在支持这些长时间运行的后台任务。您可以通过官方documentation 熟悉它们,这是我的推荐使用。

    【讨论】:

    • 非常感谢,我还有 2 个问题: - 我可以为此目的使用 Task.Run 或 IHostedService 吗? - 使用 Task.Run 是否有可能回收任务?
    • 或者我应该在什么时候使用 IHostedService 以及何时应该使用 Task.Run ?
    • 我应该用 Task.Run 包装方法调用还是应该在方法中使用 Task.Run ?
    猜你喜欢
    • 1970-01-01
    • 2016-03-17
    • 1970-01-01
    • 2019-11-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多