使用:Asp.net核心,Entityframework核心,ABP 4.5
我有一个用户注册和初始化流程。但是要花很长时间。我想对此并行化。这是由于从同一实体进行的更新,但是具有不同的字段。
我的目标:
1.端点应尽快做出响应;
2.长初始化在后台处理;
之前的代码(为简洁起见,省略了一些小细节)
public async Task<ResponceDto> Rgistration(RegModel input)
{
var user = await _userRegistrationManager.RegisterAsync(input.EmailAddress, input.Password, false );
var result = await _userManager.AddToRoleAsync(user, defaultRoleName);
user.Code = GenerateCode();
await SendEmail(user.EmailAddress, user.Code);
await AddSubEntities(user);
await AddSubCollectionEntities(user);
await CurrentUnitOfWork.SaveChangesAsync();
return user.MapTo<ResponceDto>();
}
private async Task AddSubEntities(User user)
{
var newSubEntity = new newSubEntity { User = user, UserId = user.Id };
await _subEntityRepo.InsertAsync(newSubEntity);
//few another One-to-One entities...
}
private async Task AddSubEntities(User user)
{
List<AnotherEntity> collection = GetSomeCollection(user.Type);
await _anotherEntitieRepo.GetDbContext().AddRangeAsync(collection);
//few another One-to-Many collections...
}
尝试更改:
public async Task<ResponceDto> Rgistration(RegModel input)
{
var user = await _userRegistrationManager.RegisterAsync(input.EmailAddress, input.Password, false );
Task.Run(async () => {
var result = await _userManager.AddToRoleAsync(user, defaultRoleName);
});
Task.Run(async () => {
user.Code = GenerateCode();
await SendEmail(user.EmailAddress, user.Code);
});
Task.Run(async () => {
using (var unitOfWork = UnitOfWorkManager.Begin())
{//long operation. defalt unitOfWork out of scope
try
{
await AddSubEntities(user);
}
finally
{
unitOfWork.Complete();
}
}
});
Task.Run(async () => {
using (var unitOfWork = UnitOfWorkManager.Begin())
{
try
{
await AddSubCollectionEntities(user);
}
finally
{
unitOfWork.Complete();
}
}
});
await CurrentUnitOfWork.SaveChangesAsync();
return user.MapTo<ResponceDto>();
}
错误:
在这里,我得到了很多与比赛有关的错误。频繁:
我认为服务器上的每个请求都在其流中,但显然没有。
如何保持用户实体“打开”进行更新,同时“关闭”其他请求发起的更改?如何使此代码线程安全,快速,任何人都可以提供建议吗?
最佳答案
在ASP.NET中使用Task.Run
很少是一个好主意。
异步方法无论如何都在线程池上运行,因此将它们包装在Task.Run
中只会增加开销,而没有任何好处。
在ASP.NET中使用异步的目的仅仅是为了防止线程被阻塞,从而使它们能够处理其他HTTP请求。
归根结底,数据库是瓶颈。如果所有这些操作都需要在您将响应返回给客户端之前发生,那么除了让它们发生之外,您无能为力。
如果可以提前返回并允许某些操作在后台继续运行,那么details here显示了如何完成此操作。
关于c# - 我可以在并行线程中更新一个实体吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61407545/