c#线程中的代码执行时间非固定,而是越来越长

qq_31382269 2017-11-08 11:46:18
是这样的,我创建了一个线程A,A是写在一个thread类型定时器内,用来循环执行A,循环时间设置为5S,在A中有一段for循环代码,为了测试该代码每次执行过程的大致时间,我在代码前后分别加了两个累加数,测试发现刚开始很快,不到1S就执行完毕。但随着时间的流逝,执行整段循环代码的耗时越来越长,甚至超过5S。每次重新运行都是刚开始很快,然后慢慢变慢。
因为代码里面含有对数据库的操作,每次重新运行都是刚开始很快,然后慢慢变慢。所以个人觉得应该不是数据库表中数据太多导致响应时间慢慢变长。嵌套的for循环次数也不是太多,外层12,内层16,也就12X16=192次。但是发现将其改为2X5次后,就发现耗时基本保持固定数,或者叫增长的极其缓慢。
问题1.是什么导致耗时越来越长,每次执行不应该是差不多固定时间才对嘛?
问题2.我同时监视了CPU和内存,内存一直保持很稳定,但CPU不稳定,基本每隔5秒,就是每次执行循环代码时,CPU都会明显上升,然后回落,我给循环代码内部加了sleep(1),还是解决不了问题。另外按理说12X16次数也不是很多。改为2X5后CPU基本保持稳定。那我应该如何做才能避免CPU占用高呢?
求各位给出建议,下面我贴下代码:
以下均为A()方法中的代码
num1++;
label1.text = num1.tostring();
//连接数据库
SqlConnection con = new SqlConnection();
con.ConnectionString = @"Data Source =王-THINK;Initial Catalog=hw;Integrated Security=SSPI";
con.Open();

SqlCommand com = new SqlCommand();
com.Connection = con;
com.CommandType = CommandType.Text;

for (int i = 0; i < 12; i++)
{
for (int j = 0; j < 16; j++)
{
//下面两行代码是在th这个图片类型中创建一个矩形,用来获取该矩形的最大值,引用的第三方dll,这个DLL很成熟,可以排除耗时跟它无关。
MeasurementRectangle rectangle = th.Measurements.Add(new Rectangle(j * 20, i * 20, 20, 20));
temp[i, j] = rectangle.Max.Value;
//存入数据库
com.CommandText = "insert into [Table7_Temp] (时间,时,分,秒,毫秒,行,列,温度,标识,辐射率,摄像机号,区域号,creattime,总貌X,总貌Y,总貌H,总貌W)Values(//里面的变量就赘述了,但包含 temp[i, j] );
SqlDataReader dr = com.ExecuteReader();//执行SQL语句
dr.Close();//关闭执行
}
}
con.Close();//关闭数据库连接
num2++;
label2.text = num2.tostring();
...全文
451 14 打赏 收藏 举报
写回复
14 条回复
切换为时间正序
当前发帖距今超过3年,不再开放新的回复
发表回复
流云妃 2019-04-07
  • 打赏
  • 举报
回复
qq_31382269 2017-11-09
引用 6 楼 hanjun0612 的回复:
[quote=引用 5 楼 qq_31382269 的回复:] [quote=引用 4 楼 hanjun0612 的回复:] 你试试直接timer的事件直接执行方法,别跑线程试试看
您好,试过了的,还是一样的效果,耗时会慢慢变长。[/quote] 那你先对于每个重要步骤,如录入数据库,MeasurementRectangle rectangle = th.Measurements.Add(new Rectangle(j * 20, i * 20, 20, 20)); 等等,增加一个 Stopwatch 记录日志,来观察哪些步骤增加了时间[/quote] 您好,我按照您的方法做了,发现MeasurementRectangle rectangle = th.Measurements.Add(new Rectangle(j * 20, i * 20, 20, 20));这行代码的耗时是逐步增长的,每行代码耗时乘以192差不多等于for循环前后累加数迟滞的时间。就是这行代码的问题。所以我发现每次创建的矩形居然没有销毁或删掉,粗心大意了,于是每次创建后都将其移除,执行的时间也基本差不多是固定时间了。谢谢了!
  • 打赏
  • 举报
回复
Squall001 2017-11-09
参考如下代码

CREATE TABLE test (
  ID  char(1),
  VAL varchar(5)
);
 
INSERT INTO test
  SELECT 'A',  'TRUE ' FROM dual UNION ALL
  SELECT 'A',  'TRUE ' FROM dual UNION ALL
  SELECT 'A',  'FALSE' FROM dual UNION ALL
  SELECT 'A',  'TRUE ' FROM dual UNION ALL
  SELECT 'A',  'TRUE ' FROM dual UNION ALL
  SELECT 'A',  'TRUE ' FROM dual UNION ALL
  SELECT 'A',  'FALSE' FROM dual UNION ALL
  SELECT 'A',  'TRUE ' FROM dual UNION ALL
  SELECT 'B',  'TRUE ' FROM dual UNION ALL
  SELECT 'B',  'FALSE' FROM dual UNION ALL
  SELECT 'B',  'TRUE ' FROM dual UNION ALL
  SELECT 'B',  'TRUE ' FROM dual UNION ALL
  SELECT 'B',  'FALSE' FROM dual ;
  • 打赏
  • 举报
回复
Squall001 2017-11-09
你代码优化下,用sql里面用union all关键字 把需要入库的信息全部拼起来,然后只需要执行1次数据库操作就行了,
  • 打赏
  • 举报
回复
正怒月神 2017-11-08
你试试直接timer的事件直接执行方法,别跑线程试试看
  • 打赏
  • 举报
回复
正怒月神 2017-11-08
引用 2 楼 qq_31382269 的回复:
[quote=引用 1 楼 hanjun0612 的回复:] 我创建了一个线程A,A是写在一个thread类型定时器内 你意思是在timer中又跑了一个线程嘛?
是啊,因为我要每隔5S执行一次线程A中的代码,所以写在定时器内的[/quote] 那我觉得你可以不必跑一个线程,而是直接在定时器里调用A方法就行了。 因为timer本来就是新的线程
  • 打赏
  • 举报
回复
qq_31382269 2017-11-08
引用 1 楼 hanjun0612 的回复:
我创建了一个线程A,A是写在一个thread类型定时器内 你意思是在timer中又跑了一个线程嘛?
是啊,因为我要每隔5S执行一次线程A中的代码,所以写在定时器内的
  • 打赏
  • 举报
回复
正怒月神 2017-11-08
我创建了一个线程A,A是写在一个thread类型定时器内 你意思是在timer中又跑了一个线程嘛?
  • 打赏
  • 举报
回复
bidisty 2017-11-08
主要是对数据库访问的问题,以你的代码ADO是对数据库访问生成了一个线程池,线程池容量有限,开始时线程池能高效提供你要的联接资源,后期没有资源就要等待前面去施放资源,所以ADO对你的联接有个锁和放锁的过程。那么问题一:因为联接线程池资源不足,用的比放的要快,问题二,CPU在进行资源调度。解决方案,一次性把数据库中的内容加载到内存里,提高使用效率。
  • 打赏
  • 举报
回复
大然然 2017-11-08
你的代码有改进的地方 for (int i = 0; i < 12; i++) { for (int j = 0; j < 16; j++) 这两个循环里在入库,要入100多次,访问100多次数据库, 你可以把这100个数据放在一个集合里,然后调用一次入库操作,比如批量入库,只访问一次数据库,减少了开销。
  • 打赏
  • 举报
回复
xuzuning 2017-11-08
子线程是在主线程和其他线程的缝隙(比如等待外设)间运行的,所以他没有确定的开始运行时刻,也经常会被其他线程打断 所以,执行时间不固定是正常的!甚至后创建的线程会先于先创建的线程结束运行
  • 打赏
  • 举报
回复
wanghui0380 2017-11-08
MeasurementRectangle rectangle = th.Measurements.Add(new Rectangle(j * 20, i * 20, 20, 20)); 请注销这句话,给值直接给随机,我们无法确定。剪刀法则,减去他看效果 如果减去他就好了,那么请给出这玩意的代码,我们在具体分析
  • 打赏
  • 举报
回复
正怒月神 2017-11-08
引用 5 楼 qq_31382269 的回复:
[quote=引用 4 楼 hanjun0612 的回复:] 你试试直接timer的事件直接执行方法,别跑线程试试看
您好,试过了的,还是一样的效果,耗时会慢慢变长。[/quote] 那你先对于每个重要步骤,如录入数据库,MeasurementRectangle rectangle = th.Measurements.Add(new Rectangle(j * 20, i * 20, 20, 20)); 等等,增加一个 Stopwatch 记录日志,来观察哪些步骤增加了时间
  • 打赏
  • 举报
回复
qq_31382269 2017-11-08
引用 4 楼 hanjun0612 的回复:
你试试直接timer的事件直接执行方法,别跑线程试试看
您好,试过了的,还是一样的效果,耗时会慢慢变长。
  • 打赏
  • 举报
回复
相关推荐
发帖
C#
加入

10.7w+

社区成员

.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
申请成为版主
帖子事件
创建了帖子
2017-11-08 11:46
社区公告

让您成为最强悍的C#开发者