数据集缓存:集合已修改;枚举操作可能不会执行 [英] Dataset in Cache: Collection was modified; enumeration operation might not execute

查看:324
本文介绍了数据集缓存:集合已修改;枚举操作可能不会执行的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我存储在ASP.Net WebApplication的,缓存的数据集。在这个内部网应用程序内的每个用户都使用相同的实例。在插入/更新/删除,行动将更新数据库和数据集相应的修改。

但很少我得到一个异常,表明我已经错过了一些东西。我认为它必须是与线程安全的。

 集合已修改;枚举操作可能不会执行
 

在这里我访问一​​个数据表中的数据集,例如行:

 看淡作为新数据视图(dsERP.ERP_Charge,筛选,排序,_
    Data.DataViewRowState.CurrentRows)
 

这显然是被另一个线程改变而鉴于枚举数据表。

是什么让这个线程安全的最好方法是什么?

修改:如你所说,我需要锁定的添加/编辑对象/删除操作。 MSDN *说,一个DataSet是线程安全的多个用户。这是什么意思,是在数据集的数据表也线程安全的?而如何锁定写操作的一个DataTable,而不是整个数据集?

  

* ADO.NET - 多线程编程

     

ADO.NET进行了优化,性能,吞吐量和可扩展性。其结果是,该   ADO.NET对象不锁定资源,并且必须只在单个线程中使用。唯一的那个   例外的是数据集,这是线程安全的多的读者。但是,您需要   在锁定数据集的

这是返回的数据集的属性:

 公共只读属性dsERP()作为ERPModel.dsERP
    得到
        如果高速缓存(DS_ERP)是没有那么
            缓存(DS_ERP)=新ERPModel.dsERP
            FillDataSet()
        结束如果
        返回DirectCast(高速缓存(DS_ERP),ERPModel.dsERP)
    最终获取
高端物业
 

由于casperOne我修改了插入/更新和删除以下方式操作(dsRma是一个数据集):

 昏暗的成功作为布尔
的SyncLock dsRMA.RMA
     成功=插入()
最终的SyncLock
 

首先,它现在的工作,如果另一个线程试图枚举RMA-表?其次,是它足以锁定该得到更新锁定整个数据表,而不是数据行(见下文)?

 昏暗thisRMA作为ERPModel.dsRMA.RMARow = dsRMA.RMA.FindByIdRMA(Me.IdRma)
昏暗的成功作为布尔
的SyncLock thisRMA
       成功=更新(thisRMA)
最终的SyncLock
 

解决方案

通常情况下,列举了当一个序列,则无法进行操作,将修改的顺序。

由于有啊重新存储在所述高速缓存WebApplication的集合,它可以通过在多个线程同时击中;你可能有一个线程上的请求输入高速缓存中的项目,而另一个正试图枚举了。

要解决这个问题,你真的应该访问的数据结构线程安全的。

您有几个选择这一点。第一,和最简单的,将是封装访问序列中的锁定块。不得不将添加/修改/删除各个块的操作,你也有针对于锁定同一目标块以上的的整个枚举序列。

这可以很容易地封装在另一个类,然后您存储在缓存中。

如果您还进行大量的读操作相比,写操作,那么你可以使用的 ReaderWriterLockSlim 类锁定读取和写入适当的;上述战略将锁定两个并发读取。

另一种解决方案是锁定周围的任何添加/编辑/更新操作上的缓存,而当你想列举缓存,锁定并创建序列本身的副本,并返回;一旦你返回序列的副本,您可以单独列举,作为该序列从一个你实际上是改变不同。

I'm storing a dataset in an ASP.Net WebApplication-Cache. Every user in this intranet-app uses the same instance. On insert/update/delete-actions the database will be updated and the dataset is modified accordingly.

But rarely I get an exception that indicates that I've missed something. I assume that it must have something to do with thread safety.

 Collection was modified; enumeration operation might not execute

In lines where i access a DataTable in the Dataset, for example:

Dim view As New DataView(dsERP.ERP_Charge, filter, sort, _
    Data.DataViewRowState.CurrentRows)

It was apparently changed by another thread while the view enumerates the datatable.

What is the best way to make this thread safe?

Edit: as you've mentioned i need to lock the objects on add/edit/delete operations. MSDN* says that a DataSet is thread-safe for multiple users. What does this mean, are the DataTables in the Dataset also thread-safe? And how to lock a single datatable on write-operations and not the whole dataset?

*ADO.NET - Multithreaded Programming

ADO.NET is optimized for performance, throughput, and scalability. As a result, the ADO.NET objects do not lock resources and must only be used on a single thread. The one exception is the DataSet, which is thread-safe for multiple readers. However, you need lock the DataSet during writes.

This is the property that returns the dataset:

Public ReadOnly Property dsERP() As ERPModel.dsERP
    Get
        If Cache("DS_ERP") Is Nothing Then
            Cache("DS_ERP") = New ERPModel.dsERP
            FillDataSet()
        End If
        Return DirectCast(Cache("DS_ERP"), ERPModel.dsERP)
    End Get
End Property

Thanks to casperOne i've modified the insert/update and delete operations in the following way(dsRma is a dataset):

Dim success As Boolean
SyncLock dsRMA.RMA
     success = insert()
End SyncLock

First, does it work now if another thread tries to enumerate the RMA-Table? Second, is it sufficient to lock the datarow that gets updated instead of locking the whole datatable(see below)?

Dim thisRMA As ERPModel.dsRMA.RMARow = dsRMA.RMA.FindByIdRMA(Me.IdRma)
Dim success As Boolean
SyncLock thisRMA
       success = update(thisRMA)
End SyncLock

解决方案

Generally, when enumerating over a sequence, you cannot perform operations that will modify the sequence.

Because youa re storing the collection in the WebApplication cache, it can be hit by multiple threads at the same time; you might have a request on one thread enter an item in the cache while another is trying to enumerate over it.

To combat this, you really should make access to the data structure thread-safe.

You have a few options for this. The first, and easiest, would be to encapsulate access to the sequence in a lock block. You have to wrap add/edit/delete operations in individual blocks, and you also have target the same object in a lock block over the enumeration of the entire sequence.

This can easily be encapsulated in another class and then you store that in your cache.

If you are also performing a high number of read operations compared to write operations, then you can use the ReaderWriterLockSlim class to lock reads and writes appropriately; the strategy above will lock two concurrent reads out.

Another solution would be to lock around any add/edit/update operation on the cache, and when you want to enumerate the cache, lock and create a copy of the sequence itself and return that; once you return the copy of the sequence, you can enumerate that separately as that sequence is different from the one you are actually modifying.

这篇关于数据集缓存:集合已修改;枚举操作可能不会执行的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆