使用Linq to SQL进行multithreading处理

我正在构建一个应用程序,它要求我使用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的属性,错误似乎就会抛出。

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

更新

这是我决定采用的:

 var events = new Dictionary(); 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()); 

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

抛出exception,因为实体的某些属性在先前的读取器尚未关闭时执行新查询。 您不能同时对数据上下文执行多个查询。

作为一种解决方法,您可以“访问”您在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()有很多逻辑并且查询不是很大,那么这个解决方案很好。

尝试在新线程中创建Repository而不是传入它。

请注意,SqlConnection实例不是线程安全的。 你是否仍然有一个开放的阅读器。 通常,从多个线程访问SqlConnection实例将导致不可预测的间歇性问题。

请参阅: http : //msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlconnection.aspx

我的解决方案是LightSpeed Persistence框架,它在8个实体之前是免费的。 每个线程创建单元。

http://www.mindscapehq.com/products/LightSpeed/default.aspx