gpt4 book ai didi

c# - 我可以在并行线程中更新一个实体吗?

转载 作者:行者123 更新时间:2023-12-03 13:15:00 24 4
gpt4 key购买 nike

使用: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>();
}

错误:
在这里,我得到了很多与比赛有关的错误。频繁:
  • 在上一个操作完成之前,在此上下文上启动了第二个操作。这通常是由使用相同DbContext实例的不同线程引起的。
  • 在很少的注册调用中:无法在具有唯一索引“YYY”的对象“XXX”中插入重复的键行。重复键值为(70)。该语句已终止。

  • 我认为服务器上的每个请求都在其流中,但显然没有。
  • 或所有用户都已成功注册,但他们在数据库中没有某些子实体。与找出错误的初始化位置=(
  • 相比,不注册用户要容易得多

    如何保持用户实体“打开”进行更新,同时“关闭”其他请求发起的更改?如何使此代码线程安全,快速,任何人都可以提供建议吗?

    最佳答案

    在ASP.NET中使用Task.Run很少是一个好主意。

    异步方法无论如何都在线程池上运行,因此将它们包装在Task.Run中只会增加开销,而没有任何好处。

    在ASP.NET中使用异步的目的仅仅是为了防止线程被阻塞,从而使它们能够处理其他HTTP请求。

    归根结底,数据库是瓶颈。如果所有这些操作都需要在您将响应返回给客户端之前发生,那么除了让它们发生之外,您无能为力。

    如果可以提前返回并允许某些操作在后台继续运行,那么details here显示了如何完成此操作。

    关于c# - 我可以在并行线程中更新一个实体吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61407545/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com