.net 数据表与线程安全
我正在ASP.NET缓存属性中存储DataTable。可以在该数据表上执行的操作包括:.net 数据表与线程安全,.net,asp.net,multithreading,ado.net,thread-safety,.net,Asp.net,Multithreading,Ado.net,Thread Safety,我正在ASP.NET缓存属性中存储DataTable。可以在该数据表上执行的操作包括: 绑定到网格控件(第三方网格在内部管理数据源对象,回发后其数据源为空,我假设数据绑定后不再使用数据源DataTable) 正在从数据表中删除行(Row.Delete() 我在显式地处理DATABLE实例时添加了基本的读写器锁,但是我想知道这个解决方案还有其他线程安全问题吗?我猜当网格控件处于数据绑定的中间时,可能会出错,其他线程会删除行吗?如果是,我如何同步访问那个表,以便没有删除< /s?trong>方法
- 绑定到网格控件(第三方网格在内部管理数据源对象,回发后其数据源为空,我假设数据绑定后不再使用数据源DataTable)
- 正在从数据表中删除行(Row.Delete()
我在显式地处理DATABLE实例时添加了基本的读写器锁,但是我想知道这个解决方案还有其他线程安全问题吗?我猜当网格控件处于数据绑定的中间时,可能会出错,其他线程会删除行吗?如果是,我如何同步访问那个表,以便没有<强>删除< /s?trong>方法调用是在网格控件绑定时进行的?是否有任何事件组合可以放置AcquireWriterLock和ReleaseWriterLock方法
谢谢,Pawel如果您通过数据绑定公开datatable,那么请忘记它;您无法使该线程安全。即使您以某种方式(在自定义的
ITypedList
中)包装DataView
)数据绑定对数据进行了假设,特别是<代码> IIST < /代码>等。例如,在迭代数据或在UI线程上添加行时,不会以线程竞争的方式随机改变长度。
在同一个线程上,可以通过事件进行更改…但不能跨线程。正如其他答案中提到的:
- 通常,您只缓存不可变的数据(或者至少:一旦数据存在,就将其视为不可变的),否则它就不是缓存
- 如果有人要编辑公共数据,请不要将多个请求公开给公共数据
- 如果您是通过数据绑定公开datatable,那么请忘记它;您无法使该线程安全
- 获取结果的查询非常庞大且耗时。使用该查询进行调用的页面的刷新率也非常高。因此,db引擎变得繁忙。使用缓存,我每2分钟只能获得1个db引擎调用
- 该查询的结果不同。但用户完全可以在2分钟内看到相同的结果。因此,将数据存储在缓存中2分钟是可以接受的。此外,没有其他问题,如并发性、乐观/悲观脱机锁
- 在实现缓存之前,在应用了对db的更改之后,应用程序再次发出巨大的查询,以获得结果,但差别很小
- 现在,通过缓存,更改应用于数据库并应用于缓存的数据表。然后,该数据表再次绑定到数据绑定控件。好处:无需进行WCF调用,使用大型查询获取数据+将数据表传输到web应用程序
public class AllocationQueue
{
private static object tableSyncRoot = new object();
internal void RemoveTaskRowFromAllocationQueue(Guid queueId, Guid taskId)
{
var allocationQueueEntry = GetAllocationQueueEntry(queueId);
var queueData = allocationQueueEntry.TaskIdIndexedView;
lock(tableSyncRoot)
{
int rowIndex = queueData.Find(new object[] { taskId });
queueData[rowIndex].Delete();
}
}
public DataTable GetAllocationQueue(Guid queueId, string filter)
{
var allocationQueueEntry = GetAllocationQueueEntry(queueId);
lock (tableSyncRoot)
{
var rows = allocationQueueEntry.Table.Select(filter);
if (rows.Length > 0)
{
return rows.CopyToDataTable<DataRow>();
}
}
return null;
}
公共数据表GetAllocationQueue(Guid queueId,字符串筛选器)
{
var allocationQueueEntry=GetAllocationQueueEntry(queueId);
锁(表同步器)
{
var rows=allocationQueueEntry.Table.Select(筛选器);
如果(rows.Length>0)
{
返回行。CopyToDataTable();
}
}
返回null;
}
线程安全&工作起来像个符咒(我说的对吗?:))。但是它非常符合我的要求。这里有一个以线程安全的方式添加行的简单方法。其中dt=我的数据表,dr=我的数据行
lock (dt.Rows.SyncRoot)
{
dt.Rows.Add(dr);
}
谢谢更改列值怎么样?它也会引起问题吗?我可以添加列IsDeleted,并且不使用该标志集呈现行。@dragonfly,但同样,您很可能最终从非UI线程引发事件,绑定将尝试对其作出反应-再次在非UI线程上。这反过来很可能会带来坏消息,而不是好消息。那么,我如何以安全的方式实现缓存。。。。。?DataTable.Copy()并对该副本进行绑定?关于非UI线程。我们谈论的是ASP.NET应用程序,所以这不是问题所在,是吗?@dragonfly-通常,您只缓存不可变的数据(或者至少:一旦数据存在,就将其视为不可变数据)。否则它不是缓存。。。