DataTable多线程操作报错情况

最近在写一个http接口时用了DataTable这个强大的利器,接口用浏览器跑起来没任何问题。当时也没考虑并发问题,后来用一个压力测试工具做大并发测试,1000+/s次速度测试。发现程序报错了。程序报错了第一反应还是去检查代码,是不是代码出现问题。发现逻辑都是对的,然后用浏览器打开接口,发现一切OK;然后心想肯定是并发时多个线程操作导致的。

我们都知道在多线程的时候不同的线程访问同一个资源的时候,用lock方法来达到线程同步,也就是同一个时刻同一个资源只能被一个线程操作。

我开始在操作DataTable的函数前面加上:

1 object oblock = new object();
2
3 lock(oblock)
4 {
5     //我的dataTable对rows操作的代码
6 }

信心满满的开始继续用压力测试工具来测试。结果还是报错;因为是并发操作你几乎不能用vs进行断点调试;所以也不好找到具体的错误在什么地方。然后就try catch 打印错误日志找到具体异常原因和所在代码行。提示的错误有时候都不尽相同;有“内部索引损坏”、"在位置0处没有任何行" 等等。加了lock还报错就感觉挺纳闷的;当这段代码被锁定以后应该是不会被其他线程操作,也就不会导致行的索引出现问题。

后来找些资料发现,因为我们平时对DataTable的操作基本是Rows操作,所以我上面lock的代码里面只锁定了DataTable的Rows;但是因为我没有操作Columns,所以其他线程还可以访问DataTable的Columns集合。但是Rows是共享一个Columns的;罪魁祸首应该是没有锁住Columns导致的。

解决方法:

通过百度知道.Net里DataTable.Rows集合上提供.SyncRoot同步对象,正是为了在多线程环境下锁住DataTable中的Rows集合同时也锁住了Columns集合。

所以我们只需要在要操作DataTable代码的前面加上:


1 //你要操作的 DataTable
2 DataTable dtb = new DataTable();
3 lock(dtb.Rows.SyncRoot)
4 {
5    //你的DataTable处理代码
6 }

注:并不是所有DataTable在多线程操作是都会报错;视具体情况而定。但是为了线程安全在多线程下操作是最好加上Rows.SyncRoot锁。

				
时间: 2025-01-09 13:44:57

DataTable多线程操作报错情况的相关文章

SVN 操作报错 “Previous operation has not finished; run 'cleanup' if it was interrupted“

今天在 通过 SVN 合并代码的时候报了如下的错误 "Previous operation has not finished; run 'cleanup' if it was interrupted",无论尝试什么操作都是报相同的错误,遂在网上找了资料查了一下,问题解决了,记录一下问题解决的方法. 1.下载  sqlite 内嵌数据库管理工具 sqlite3.exe 2.将sqlite3.exe 放置于SVN 项目的.svn 文件内,如图 3.删除 sqlite 数据库中的操作队列表

dojo处理删除操作报错

1.错误描述    java.lang.IllegalArgumentException:attempt to create delete event with null entity. 2.错误原因    dojo.xhrPost({         url:"", content:{     "userId":userId         },         success:function(data)         {         }    });  

linux下对文件操作报错----------Unable to *** ***: Read-only file system

在linux中对文件操作时报错:Unable to chmod ***: Read-only file system 用如下指令能解决该问题: 输入su root 进入超级用户 输入 mount -o remount rw / 然后可输入 mount 查看

C#中对指针操作报错解决方法

(C#中实际不存在指针,这里是仿C语言中指针操作进行说明) 1.错误1      “指针和固定大小缓冲区只能在不安全的上下文中使用” 解决方法:在方法前加上unsafe关键字 2.错误2 “不安全代码只会在使用 /unsafe 编译的情况下出现” 解决方法:右键选中资源管理器中项目文件--属性--生成--勾选"允许不安全代码复选框"! 事例代码,取变量a的内存地址并输出: using System; using System.Collections.Generic; using Sys

python+selenium3+firefox中使用ActionChains双击等鼠标事件操作报错,但是其它谷歌、ie等浏览器均正常

raise exception_class(message, screen, stacktrace)selenium.common.exceptions.WebDriverException: Message: POST /session/ba4e5dd2-0fdc-4aaa-8641-15e8049fab8f/moveto did not match a known command 这是Mozilla/geckodriver的一个bug,由于geckodriver开发是2016年中旬的,所以只

redis 命令行操作报错

向redis集群写数据抛异常:(error) MOVED 15342 2001:fecc:0:616::34:6383 原因是启动redis-cli时未以集群方式启动,即后面要加上 -c redis-cli -h [ip] -p [port] -c 原文地址:https://www.cnblogs.com/kuku0223/p/10907801.html

puppet 报错

新服务器装完系统后,安装puppet后执行如下操作报错: 执行puppet agent -t的时候报错: Aug 30 09:14:28 masterdb puppet-agent[66746]: Unable to fetch my node definition, but the agent run will continue: Aug 30 09:14:28 masterdb puppet-agent[66746]: getaddrinfo: Name or service not kno

[问题记录]cocos的lua绑定安装pyyaml报错

描述:按照readme中的文档操作报错,提示python2.7没有安装,但是确实已经安装了,而且也设置环境变量成功了. 解决: 在D盘新建register.py的文件,内容如下: # # script to register Python 2.0 or later for use with win32all # and other extensions that require Python registry settings # # written by Joakim Loew for Sec

django在读取数据库时未筛选到符合条件的记录会报错

(1)报错情况如下: DoesNotExist: Publisher matching query does not exist. (2)处理方法: try:    p = Publisher.objects.get(name='Apress')except Publisher.DoesNotExist:    print "Apress isn't in the database yet."else:    print "Apress is in the database.