.NET 正确的任务使用
.NET Correct Task use
我是 .NET Tasks 和异步编码的新手,所以我想知道在我的情况下我应该做什么:
我有一个接收 XML 文件的 .NET Core WebApi,它充当以下过程的触发器:
- 我需要 "background" 中 运行 的进程,所以我的意思是 API 调用者应该立即得到响应,然后进程应该 运行
- 我需要将 XML 解析为对象
- 有了这个数据,我需要联系3 APIs
- 如果其中任何 API 没有响应或无法检索所需数据,我们需要停止并记录此
- 如果检索到所有数据,我需要对这些数据进行计算(从数据库中获取一些数据并使用 API & 数据库数据进行计算)
计算完成后,我需要发送邮件联系另一个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" });
}
我现在的问题:
- 什么时候需要使用Task.Run(() => {});在 GetApiData1()、GetApiData2() 方法内部进行 Http 调用 ?
- 我需要在 Task.Run(() => {}); 中调用 GetApi 方法吗? ?
- 一般来说,我什么时候需要使用 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" });
}
非常感谢!
您可以使用 Task.Run
而不使用 await
到 "offload" 一些工作到 ThreadPool
的另一个线程是正确的。这样做时,您的请求的响应时间不会受到其中完成的工作的影响。
但是,在该函数内部发生的任何异常都不会被抛出给 调用者 线程(因为不等待调用)。这实际上意味着您的 try-catch 块将仅捕获在创建新 Task
时发生的异常(通过 Task.Run
方法)。换句话说,它不会捕获在处理传递给 Task.Run
方法的 lambda 时发生的任何错误。
因此,在您的情况下,第二种方法是正确的(具有上述缺点)。
此外,IIS 将等待 运行 个线程完成并在 回收 时退出,受线程池上设置的超时限制。所以,如果执行时间大于超时时间,线程就会被强行杀死。
最后,在 .Net Core 中引入了新型服务,它们被称为托管服务并实现了 IHostedService. They are built to support these kind of long running background tasks. You can get familiar with them via official documentation,这是我推荐使用的。
我是 .NET Tasks 和异步编码的新手,所以我想知道在我的情况下我应该做什么:
我有一个接收 XML 文件的 .NET Core WebApi,它充当以下过程的触发器:
- 我需要 "background" 中 运行 的进程,所以我的意思是 API 调用者应该立即得到响应,然后进程应该 运行
- 我需要将 XML 解析为对象
- 有了这个数据,我需要联系3 APIs
- 如果其中任何 API 没有响应或无法检索所需数据,我们需要停止并记录此
- 如果检索到所有数据,我需要对这些数据进行计算(从数据库中获取一些数据并使用 API & 数据库数据进行计算)
计算完成后,我需要发送邮件联系另一个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" });
}
我现在的问题:
- 什么时候需要使用Task.Run(() => {});在 GetApiData1()、GetApiData2() 方法内部进行 Http 调用 ?
- 我需要在 Task.Run(() => {}); 中调用 GetApi 方法吗? ?
- 一般来说,我什么时候需要使用 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" });
}
非常感谢!
您可以使用 Task.Run
而不使用 await
到 "offload" 一些工作到 ThreadPool
的另一个线程是正确的。这样做时,您的请求的响应时间不会受到其中完成的工作的影响。
但是,在该函数内部发生的任何异常都不会被抛出给 调用者 线程(因为不等待调用)。这实际上意味着您的 try-catch 块将仅捕获在创建新 Task
时发生的异常(通过 Task.Run
方法)。换句话说,它不会捕获在处理传递给 Task.Run
方法的 lambda 时发生的任何错误。
因此,在您的情况下,第二种方法是正确的(具有上述缺点)。 此外,IIS 将等待 运行 个线程完成并在 回收 时退出,受线程池上设置的超时限制。所以,如果执行时间大于超时时间,线程就会被强行杀死。
最后,在 .Net Core 中引入了新型服务,它们被称为托管服务并实现了 IHostedService. They are built to support these kind of long running background tasks. You can get familiar with them via official documentation,这是我推荐使用的。