multithreading - 使用依赖注入的多线程连接对象
问题描述
我一直在尝试在现有应用程序中添加并行 foreach,但遇到了一个奇怪的问题
应用架构
- 控制器解析BO层
- BO层解析服务层
- 服务层解析 UOW 和存储库层
- UOW 层解析数据库连接
BO层
private IUserService _userService;
public BOUser(IUserService userService) => _userService=userService;
public void AddUser(User user) => _userService.addUser(user);
服务层
private IUnitofWork _uow;
private IUserRepository _userRepo;
UserService(IUOW _uow, IUserRepository _userRepo)
{
uow = _uow;
_userRepo.uow = _uow;
}
public void AddUser (User user) {
_uow.BeginTransaction();
_userRepo.Add(user);
_uow.CommitTransaction();
}
回购层
public IUnitOfWork UnitOfWork { get; set; }
public void Add(user){
UnitOfWork.Connection.Insert<UserContact>(userContact, UnitOfWork.Transaction);
}
工作单元
public UnitOfWork(IDbConnection connection)
{
Connection = connection; // responsible for creating new connection
}
这在今天工作正常,但是当我尝试在 BO 层中使用 parallel.foreach 添加多个用户时,我得到一个失败和一个成功
背后的原因是服务层在 BO 层启动时启动,当我尝试多个线程时,整个进程的 UOW.connection 仍然为 1,因为 Connection 是一个在多个线程之间共享的对象,它失败了,因为一个线程完成了工作并关闭了 Connection 对象
我通过从构造函数中删除 UOW 并使用服务位置模式来考虑解决方案
IUserSrevice userService = new UserService();
这将基于线程创建多个连接对象。
这不是仪式的方式。任何专家意见都会有所帮助
解决方案
Connection
不是线程安全的对象,因为它的想法是创建一个连接对象池,并让每个线程从池中借用一个连接,完成其工作并在完成后将其返回到池中。
因此,一次最多只能有一个线程访问一个连接对象。
您应该注入连接池而不是单个连接对象。
推荐阅读
- kubernetes - kubernets pod 在挂载之前使用 configmap
- xamarin.android - 我想用事件制作滑块来捕获 Xamarin.Android 中的值
- sql - 过程问题 SQL Server 出现错误
- android - 创建的工具栏无法在 Android 设备上正确显示
- css - 打字稿的 CSS 界面
- android - 如果在 CoordinatorLayout 中设置了anchorView,则浮动操作按钮不与 Snackbar 一起浮动
- java - 我无法在我的 android 模拟器中接收 Firebase Cloud Messaging FCM
- macos - 如何在 Mac 上安装 Tesseract 5.0.0 alpha?
- c++ - 如何从启动时最大化cpp程序中的窗口?
- windows - 如何通过单击从 Windows 中的 Go 可执行文件打开特定文件