因为代码里面含有对数据库的操作,每次重新运行都是刚开始很快,然后慢慢变慢。所以个人觉得应该不是数据库表中数据太多导致响应时间慢慢变长。嵌套的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();
13 个解决方案
#1
我创建了一个线程A,A是写在一个thread类型定时器内
你意思是在timer中又跑了一个线程嘛?
你意思是在timer中又跑了一个线程嘛?
#2
是啊,因为我要每隔5S执行一次线程A中的代码,所以写在定时器内的
#3
那我觉得你可以不必跑一个线程,而是直接在定时器里调用A方法就行了。
因为timer本来就是新的线程
#4
你试试直接timer的事件直接执行方法,别跑线程试试看
#5
你试试直接timer的事件直接执行方法,别跑线程试试看
您好,试过了的,还是一样的效果,耗时会慢慢变长。
#6
你试试直接timer的事件直接执行方法,别跑线程试试看
您好,试过了的,还是一样的效果,耗时会慢慢变长。
那你先对于每个重要步骤,如录入数据库,MeasurementRectangle rectangle = th.Measurements.Add(new Rectangle(j * 20, i * 20, 20, 20));
等等,增加一个 Stopwatch 记录日志,来观察哪些步骤增加了时间
#7
MeasurementRectangle rectangle = th.Measurements.Add(new Rectangle(j * 20, i * 20, 20, 20));
请注销这句话,给值直接给随机,我们无法确定。剪刀法则,减去他看效果
如果减去他就好了,那么请给出这玩意的代码,我们在具体分析
请注销这句话,给值直接给随机,我们无法确定。剪刀法则,减去他看效果
如果减去他就好了,那么请给出这玩意的代码,我们在具体分析
#8
子线程是在主线程和其他线程的缝隙(比如等待外设)间运行的,所以他没有确定的开始运行时刻,也经常会被其他线程打断
所以,执行时间不固定是正常的!甚至后创建的线程会先于先创建的线程结束运行
所以,执行时间不固定是正常的!甚至后创建的线程会先于先创建的线程结束运行
#9
你的代码有改进的地方
for (int i = 0; i < 12; i++)
{
for (int j = 0; j < 16; j++)
这两个循环里在入库,要入100多次,访问100多次数据库,
你可以把这100个数据放在一个集合里,然后调用一次入库操作,比如批量入库,只访问一次数据库,减少了开销。
for (int i = 0; i < 12; i++)
{
for (int j = 0; j < 16; j++)
这两个循环里在入库,要入100多次,访问100多次数据库,
你可以把这100个数据放在一个集合里,然后调用一次入库操作,比如批量入库,只访问一次数据库,减少了开销。
#10
主要是对数据库访问的问题,以你的代码ADO是对数据库访问生成了一个线程池,线程池容量有限,开始时线程池能高效提供你要的联接资源,后期没有资源就要等待前面去施放资源,所以ADO对你的联接有个锁和放锁的过程。那么问题一:因为联接线程池资源不足,用的比放的要快,问题二,CPU在进行资源调度。解决方案,一次性把数据库中的内容加载到内存里,提高使用效率。
#11
你代码优化下,用sql里面用union all关键字 把需要入库的信息全部拼起来,然后只需要执行1次数据库操作就行了,
#12
参考如下代码
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 ;
#13
你试试直接timer的事件直接执行方法,别跑线程试试看
您好,试过了的,还是一样的效果,耗时会慢慢变长。
那你先对于每个重要步骤,如录入数据库,MeasurementRectangle rectangle = th.Measurements.Add(new Rectangle(j * 20, i * 20, 20, 20));
等等,增加一个 Stopwatch 记录日志,来观察哪些步骤增加了时间
您好,我按照您的方法做了,发现MeasurementRectangle rectangle = th.Measurements.Add(new Rectangle(j * 20, i * 20, 20, 20));这行代码的耗时是逐步增长的,每行代码耗时乘以192差不多等于for循环前后累加数迟滞的时间。就是这行代码的问题。所以我发现每次创建的矩形居然没有销毁或删掉,粗心大意了,于是每次创建后都将其移除,执行的时间也基本差不多是固定时间了。谢谢了!
#1
我创建了一个线程A,A是写在一个thread类型定时器内
你意思是在timer中又跑了一个线程嘛?
你意思是在timer中又跑了一个线程嘛?
#2
我创建了一个线程A,A是写在一个thread类型定时器内
你意思是在timer中又跑了一个线程嘛?
是啊,因为我要每隔5S执行一次线程A中的代码,所以写在定时器内的
#3
我创建了一个线程A,A是写在一个thread类型定时器内
你意思是在timer中又跑了一个线程嘛?
是啊,因为我要每隔5S执行一次线程A中的代码,所以写在定时器内的
那我觉得你可以不必跑一个线程,而是直接在定时器里调用A方法就行了。
因为timer本来就是新的线程
#4
你试试直接timer的事件直接执行方法,别跑线程试试看
#5
你试试直接timer的事件直接执行方法,别跑线程试试看
您好,试过了的,还是一样的效果,耗时会慢慢变长。
#6
你试试直接timer的事件直接执行方法,别跑线程试试看
您好,试过了的,还是一样的效果,耗时会慢慢变长。
那你先对于每个重要步骤,如录入数据库,MeasurementRectangle rectangle = th.Measurements.Add(new Rectangle(j * 20, i * 20, 20, 20));
等等,增加一个 Stopwatch 记录日志,来观察哪些步骤增加了时间
#7
MeasurementRectangle rectangle = th.Measurements.Add(new Rectangle(j * 20, i * 20, 20, 20));
请注销这句话,给值直接给随机,我们无法确定。剪刀法则,减去他看效果
如果减去他就好了,那么请给出这玩意的代码,我们在具体分析
请注销这句话,给值直接给随机,我们无法确定。剪刀法则,减去他看效果
如果减去他就好了,那么请给出这玩意的代码,我们在具体分析
#8
子线程是在主线程和其他线程的缝隙(比如等待外设)间运行的,所以他没有确定的开始运行时刻,也经常会被其他线程打断
所以,执行时间不固定是正常的!甚至后创建的线程会先于先创建的线程结束运行
所以,执行时间不固定是正常的!甚至后创建的线程会先于先创建的线程结束运行
#9
你的代码有改进的地方
for (int i = 0; i < 12; i++)
{
for (int j = 0; j < 16; j++)
这两个循环里在入库,要入100多次,访问100多次数据库,
你可以把这100个数据放在一个集合里,然后调用一次入库操作,比如批量入库,只访问一次数据库,减少了开销。
for (int i = 0; i < 12; i++)
{
for (int j = 0; j < 16; j++)
这两个循环里在入库,要入100多次,访问100多次数据库,
你可以把这100个数据放在一个集合里,然后调用一次入库操作,比如批量入库,只访问一次数据库,减少了开销。
#10
主要是对数据库访问的问题,以你的代码ADO是对数据库访问生成了一个线程池,线程池容量有限,开始时线程池能高效提供你要的联接资源,后期没有资源就要等待前面去施放资源,所以ADO对你的联接有个锁和放锁的过程。那么问题一:因为联接线程池资源不足,用的比放的要快,问题二,CPU在进行资源调度。解决方案,一次性把数据库中的内容加载到内存里,提高使用效率。
#11
你代码优化下,用sql里面用union all关键字 把需要入库的信息全部拼起来,然后只需要执行1次数据库操作就行了,
#12
参考如下代码
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 ;
#13
你试试直接timer的事件直接执行方法,别跑线程试试看
您好,试过了的,还是一样的效果,耗时会慢慢变长。
那你先对于每个重要步骤,如录入数据库,MeasurementRectangle rectangle = th.Measurements.Add(new Rectangle(j * 20, i * 20, 20, 20));
等等,增加一个 Stopwatch 记录日志,来观察哪些步骤增加了时间
您好,我按照您的方法做了,发现MeasurementRectangle rectangle = th.Measurements.Add(new Rectangle(j * 20, i * 20, 20, 20));这行代码的耗时是逐步增长的,每行代码耗时乘以192差不多等于for循环前后累加数迟滞的时间。就是这行代码的问题。所以我发现每次创建的矩形居然没有销毁或删掉,粗心大意了,于是每次创建后都将其移除,执行的时间也基本差不多是固定时间了。谢谢了!