【问题标题】:How to handle thread isolation in C#如何在 C# 中处理线程隔离
【发布时间】:2018-02-15 12:22:53
【问题描述】:

我正在开发一个实体框架中的多线程程序,其中我面临一个问题。我有一个多个数据库的列表,对于每个数据库我需要执行一些操作(插入/更新),目前我面临线程之间的竞争条件问题,其中我得到实体框架的错误。

异常:- 底层提供程序在打开时失败。

InnerException :- 连接没有关闭。连接的当前状态为正在连接。

我用过static readonly object Locker = new object();

lock (Locker)

但这会一个一个地执行线程。有什么方法可以一次生成所有线程,而不会出现实体框架错误,即在线程隔离中执行。

我的代码如下

var keyController = _empUnitOfWork.Repository<KeyController>()
                                        .Get(x => x.Type.Equals("X") && x.IsOnline).AsNoTracking().ToList();
        var taskList = new Task[keyController.Count];
        for (var i = 0; i < keyController.Count; i++)
        {
            var idx = i;
            var otherUnitOfWork = new TestUnitOfWork(_logger);
            otherUnitOfWork.SetSiteDbContext(_empUnitOfWork, keyController[idx].Id);
            taskList[idx] = Task.Factory.StartNew(() =>
            {
                 OtherMethodToBeExecutedOnMultipleThread(keyController[idx], otherUnitOfWork);
            });

        }
        // Wait for all tasks to complete.
        Task.WaitAll(taskList);

【问题讨论】:

  • 我知道您使用的是 EF,但您是否在任何时候都将 SqlConnection 声明为类变量,然后在多个方法中重用它?
  • here 是一些解决方案。
  • 您的变量_logger_empUnitOfWork 是线程安全的吗?它们可能同时用于多个线程。
  • 尤其是SetSiteDbContext 看起来很可疑......真的为每个工作单元设置相同的DbContext 吗?
  • 你说“线程隔离执行”对我来说是一个奇怪的短语。 进程是操作系统的隔离单元。 thread 是操作系统的execution 单元。如果您需要隔离,请使用进程。

标签: c# multithreading entity-framework-6 task-parallel-library


【解决方案1】:

大家好,感谢您的回复, 我找到了一个解决方案,我现在为每个线程初始化新的数据库上下文。它按预期工作并且可以一次生成所有线程。

【讨论】:

  • 为什么要在多个线程中使用 EF?它不会使慢查询运行得更快,它会在服务器上造成更多的锁定和争用。如果您的查询速度较慢,可以通过更好的索引找到解决方法,避免加载不必要的数据,在服务器而不是客户端进行聚合。
  • 如果要避免阻塞客户端,请使用ToList()ToArray()等的异步版本,即ToListAsync()ToArrayAsync()
  • 如果你想加载多个对象不要执行多个命令。编写一个 LINQ 查询,生成带有myIdList.Contains(myEntity.ID)ID IN (...) 子句。
猜你喜欢
  • 2015-03-23
  • 1970-01-01
  • 1970-01-01
  • 2017-09-23
  • 2010-12-23
  • 1970-01-01
  • 1970-01-01
  • 2020-01-21
  • 2023-03-07
相关资源
最近更新 更多