使用 Linq to SQL 进行多线程处理

2024-03-01

我正在构建一个应用程序,它需要我使用 DataContext 的内部线程。我的应用程序不断抛出异常InvalidOperationException类似于:

There is already an open DataReader associated with this Command which must be closed first

ExecuteReader requires an open and available Connection. The connection's current state is connecting

这些异常是间歇性的。

这是我的代码片段:

var repo = new Repository();
var entities = repo.GetAllEntities();
foreach (var entity in entities)
{
    ThreadPool.QueueUserWorkItem(
        delegate
        {
            try
            {
                 ProcessEntity(entity);
            }
            catch (Exception)
            {
                throw;
            }
        });
}

我认为这可能与将实体从主线程传递到线程有关,因为一旦我尝试访问以下属性,错误似乎就会抛出entity.

任何人都知道为什么会发生这种情况以及我该如何解决它?

Update

这是我决定采用的:

var events = new Dictionary<int, AutoResetEvent>();
var repo = new Repository();
var entities = repo.GetAllEntities();
foreach (var entity in entities)
{
    events.Add(entity.ID, new AutoResetEvent(false));
    ThreadPool.QueueUserWorkItem(
        delegate
        {
            var repo = new Repository();
            try
            {
                ProcessHierarchy(repo.GetEntity(entity.ID), ReportRange.Weekly);
            }
            catch (Exception)
            {
                throw;
            }
            finally
            {
                events[entity.ID].Set();
            }
        });
}

WaitHandle.WaitAll(events.Values.ToArray());

欢迎改进/建议,但这似乎已经成功了。


由于实体的某些属性执行新查询而先前的读取器尚未关闭,因此会引发异常。您不能同时对数据上下文执行多个查询。

作为解决方法,您可以“访问”您访问的属性ProcessEntity()并使 SQL 在线程之前运行。

例如:

var repo = new Repository();
var entities = repo.GetAllEntities();
foreach (var entity in entities)
{
    var localEntity = entity; // Verify the callback uses the correct instance
    var entityCustomers = localEntity.Customers;
    var entityOrders = localEntity.Orders;
    var invoices = entityOrders.Invoices;
    ThreadPool.QueueUserWorkItem(
        delegate
        {
            try
            {
                 ProcessEntity(localEntity);
            }
            catch (Exception)
            {
                throw;
            }
        });
}

此解决方法将仅在主线程上执行 SQL,而处理将在其他线程中完成。由于所有查询都是在单个线程中完成的,因此您会失去一些效率。如果您有很多逻辑,那么这个解决方案很好ProcessEntity()而且查询量也不是很大。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用 Linq to SQL 进行多线程处理 的相关文章

随机推荐