【发布时间】:2023-03-06 13:48:02
【问题描述】:
我有一个控制器,它调用一个服务方法,这个方法调用同步一个存储过程
服务:
public class ServiceSomething : IServiceSomething, IService {
public int ProcessSomethingInDatabase(List<SqlParameter> sqlParameters){
IConnection connection = ConnectionFactory.GetConnection();
//This makes a synchronous call
DataTable dataTable = Connection.DalDataTable("sp_process_something", sqlParameters);
int result = GetResultFromDataTable(dataTable);
return result;
}
}
控制器:
public class SomethingController : Controller {
private readonly IServiceSomething _serviceSomething;
[HttpPost]
public async Task<CustomResult> ProcessSomethingInDatabase(Criteria criteria){
List<SqlParameter> sqlParameters = CriteriaToSqlParams(criteria);
int result = await Task.Run(() => _serviceSomething.ProcessSomethingInDatabase(sqlParameters));
return new CustomResult(result);
}
}
该过程可能需要很长时间(有时需要 30 秒到 1 小时)。
问题在于同步调用冻结了应用程序,因此我们使用了 Task.Run。有人要求我不要在控制器中初始化线程。
现在我想知道什么是最好的实现,只要不冻结应用程序并处理可能需要数小时才能完成的过程。
我真的应该为此创建一个线程吗?
public async Task<int> ProcessSomethingInDatabaseAsync(List<SqlParameter> sqlParameters){
IConnection connection = ConnectionFactory.GetConnection();
return await Task.Run(() => {
DataTable dataTable = Connection.DalDataTable("sp_process_something", sqlParameters);
int result = GetResultFromDataTable(dataTable);
return result;
});
}
控制器是
[HttpPost]
public async Task<CustomResult> ProcessSomethingInDatabase(Criteria criteria){
List<SqlParameter> sqlParameters = CriteriaToSqlParams(criteria);
int result = await _serviceSomething.ProcessSomethingInDatabaseAsync(sqlParameters);
return new CustomResult(result);
}
还是应该使用 Task.FromResult?
public Task<int> ProcessSomethingInDatabaseAsync(List<SqlParameter> sqlParameters){
IConnection connection = ConnectionFactory.GetConnection();
DataTable dataTable = Connection.DalDataTable("sp_process_something", sqlParameters);
int result = GetResultFromDataTable(dataTable);
return Task.FromResult(result);
}
注意: 该服务托管在 Windows 服务上,并通过 WCF 进行通信
【问题讨论】:
-
the synchronous call freezes the application- 然后修复该应用程序,使其不会在其网络调用中冻结。在 ASP.NET 方面,这很好。无论如何,请求在完成之前都不会返回,这方面没有任何异步。在控制器中执行 Task.Run 是 considered harmful. -
两者都不:您需要
DalDataTableAsync方法。你应该await实际async方法一直到执行存储过程的方法。 -
@madreflection 什么是真正的异步方法?
-
如果这个数据库调用可能需要几分钟/几小时,那么它应该在 http 调用的范围之外完成!查看
IHostedServiceimplementations,这是在与 Web 服务相同的应用程序中实现此功能的众多方法之一(还有很多其他方法)
标签: c# asp.net .net asp.net-mvc