DataTable多线程操作报错情况
最近在写一个http接口时用了DataTable这个强大的利器,接口用浏览器跑起来没任何问题。当时也没考虑并发问题,后来用一个压力测试工具做大并发测试,1000+/s次速度测试。发现程序报错了。程序报错了第一反应还是去检查代码,是不是代码出现问题。发现逻辑都是对的,然后用浏览器打开接口,发现一切OK;然后心想肯定是并发时多个线程操作导致的。
我们都知道在多线程的时候不同的线程访问同一个资源的时候,用lock方法来达到线程同步,也就是同一个时刻同一个资源只能被一个线程操作。
我开始在操作DataTable的函数前面加上:
object oblock = new object(); lock(oblock)
{
//我的dataTable对rows操作的代码
}
信心满满的开始继续用压力测试工具来测试。结果还是报错;因为是并发操作你几乎不能用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锁。
DataTable多线程操作报错情况的更多相关文章
- dotnetcore ef 调用多个数据库时用户命令执行操作报错
dotnetcore ef 调用多个数据库时用户命令执行操作报错 1.多个DbContext 时报错: 报错: More than one DbContext was found. Specify w ...
- Ansible 脚本运行一次后,再次运行时出现报错情况,原因:ansible script 的格式不对,应改成Unix编码
Ansible 脚本运行一次后,再次运行时出现报错情况,原因:ansible script 的格式不对,应改成Unix编码 find . -name "*" | xargs do ...
- ORACLE数据导入导出后新数据库中某些表添加操作报错[ORA-12899]
由于项目需要,我在搭建了新的开发环境后,需要将之前环境中的ORACLE数据库导出,再导入到新的开发环境下.当导出导入完成后,使用数据库进行添加操作时 发现针对很多表的添加操作报错,具体报错原因描述为: ...
- 【疑难杂症】gdb调试多线程程序报错:interrupted system call
一. cmake生成可调试版本的程序,该内容参考自https://www.linuxidc.com/Linux/2014-03/98622.htm 具体内容如下: 1, 使用CMAKE编译确实很方便. ...
- 解决升级Spark2.0之后,DataFrame map操作报错
当我们在使用spark1.6的时候,当我们创建SQLContext读取一个文件之后,返回DataFrame类型的变量可以直接.map操作,不会报错.但是升级之后会包一个错误,如下: 报错:No imp ...
- postgresql shell发起select操作报错ERROR: relation "tablename" does not exist
最近安装了一套clourdera manager,其中hive元数据保存在postgresql中,因为今天想看一下hive的元数据信息,就登录了psql,连接到hive元数据库,发起select操作, ...
- Elasticsearch聚合操作报错解决办法
1. 当根据一个类型为text的字段idc进行聚合操作时,查询语句如下: { "aggs": { "top_10_states": { "terms& ...
- 解决Git操作报错
情况一: 当我拉取的代码是最新的时候,git pull是可以正常的拉取的,但是却不可以提交,报错如下图: 情况二: 如果我目前不是最新的版本,需要git pull,此时拉取就会失败,报错如下图: 出现 ...
- Eclipse/MyEclipse向HDFS中如创建文件夹等操作报错permission denied解决办法
不多说,直接上干货! 问题现象 当执行创建文件的的时候, 即: String Path = "hdfs://host2:9000"; FileSystem fileSystem = ...
随机推荐
- Qt 之 入门例程(二)
本文以 Qt 中的 QtConcurrent::run() 函数为例,介绍如何将函数运行在单独的某一个线程中. 1 QtConcurrent::run() QtConcurrent 是一个命名空间, ...
- $>_<$
Hello word! 从jdk环境变量的配置,myeclipse的安装,tomcat的部署和使用,面向对象的编程思想,什么是java. 思维从模糊到清晰,一路摸索,不见泰山!
- [笔记]ACM笔记 - 自用模板
长期更新. 快速幂 lld pow_mod(lld a, lld b, const int &pr) { lld ans = 1; while (b) { if (b & 1) ans ...
- CAS单点登录服务器搭建
关于cas单点登录的原理及介绍这里不做说明了,直接开始: 1.war包下载 去官网(https://www.apereo.org/projects/cas/download-cas)下载cas_ser ...
- 通过分析 JDK 源代码研究 TreeMap 红黑树算法实
TreeMap和TreeSet是Java Collection Framework的两个重要成员,其中TreeMap是Map接口的常用实现类,而TreeSet是Set接口的常用实现类.虽然HashMa ...
- 区块链入门(2):搭建以太坊私有链(private network of ethereum),以及挖矿的操作..
在做一些测试工作的时候, 为了方便控制以及更快的进入真正的测试工作,可能需要搭建一个私有的以太坊网络. 而以太坊节点之间能够互相链接需要满足1)相同的协议版本2)相同的networkid,所以搭建私有 ...
- CentOS 6.x 本地yum源配置与使用
系统默认已经安装了可使用yum的软件包,所以可以直接配置: # mount /dev/cdrom /mnt 挂载镜像,可以写到配置文件 ...
- Linux C 程序的开发环境
1.开发环境的构成 编辑器 vim,vi 编译器 gcc 调试器 gdb 函数库glibc 系统头文件glibc_header 2.gcc编译器 功能强大.性能优越的多平台编译器,gcc可以将c.c+ ...
- Java基础知识二次学习-- 第一章 java基础
基础知识有时候感觉时间长似乎有点生疏,正好这几天有时间有机会,就决定重新做一轮二次学习,挑重避轻 回过头来重新整理基础知识,能收获到之前不少遗漏的,所以这一次就称作查漏补缺吧!废话不多说,开始! 第一 ...
- 多线程编程-- part 3 多线程同步->synchronized关键字
多线程同时访问一个资源,可以会产生不可预料的结果,所以为这个资源加锁,访问资源的第一个线程为其加锁后,其他线程便不能在使用那个资源,直到锁被解除. 举个例子: 存款1000元,能取出800的时候我就取 ...