注册 登录
编程论坛 VFP论坛

这段程序运行中经常造成系统无响应,大侠们看看,问题出在哪里啊

Pgwyg 发布于 2022-06-12 09:18, 2798 次点击
1,经常在19:00:00点停止写数据
2,经常在23:59:59引起程序无响应,此时必须用程序管理器终止程序
3,不定时发生,发生的时间一定是上面的时间
4,使用TRY没有捕捉到任何错误信息
星号下是程序,烦请各位大侠看看,谢了!


*
当前时间=DATETIME()
*显示时间
IF thisform.timexs.Caption!=TTOC(当前时间)
    *更新时间显示
    thisform.timexs.Caption=TTOC(当前时间)
    *整点(每60分钟)保存一次水表数据
    IF MINUTE(当前时间)=0 AND sec(当前时间)=0 &&
        累计供水=THISFORM.TEXT10.Value
        当日用水=THISFORM.TEXT11.VALUE
        累计回水=THISFORM.TEXT12.Value
        当日回水=THISFORM.TEXT13.Value
        INSERT INTO DATA\COUNT_DATA (编号,采集,累计,当日) VALUES (yh_gsbh,当前时间,ALLTRIM(STR(累计供水,20,5)),ALLTRIM(STR(当日供水,20,5)))
        INSERT INTO DATA\COUNT_DATA (编号,采集,累计,当日) VALUES (yh_hsbh,当前时间,ALLTRIM(STR(累计回水,20,5)),ALLTRIM(STR(当日回水,20,5)))
        thisform.label25.CAPTION=TTOC(当前时间)+" 供水和回水流量计(水表) 的数据已经保存! "   
    ENDIF
    *每天23时为水表日结算时刻,数据初始化
    IF HOUR(当前时间)=23&& AND MINUTE(当前时间)=59 AND SEC(当前时间)=59   
        上报状态=.F.
        昨日供水=累计供水
        当日供水=0
        昨日回水=累计回水
        当日回水=0
        THISFORM.TEXT10.Value=累计供水
        THISFORM.TEXT11.VALUE=当日供水
        THISFORM.TEXT12.Value=累计回水
        THISFORM.TEXT13.Value=当日回水   
    ENDIF
    *每日4时自动推送数据,如果不成功,在此时间内相隔10分钟再次推送
    IF HOUR(当前时间)=4 AND MOD(MINUTE(当前时间),10)=0
        IF 上报状态=.F.
            THISFORM.上报()
        ENDIF
    ENDIF
    *每天早上6时开始采集水表数据,0 时结束
    IF HOUR(当前时间)>=6 AND HOUR(当前时间)<>0    &&AND MINUTE(当前时间)=0 AND SEC(当前时间)=0
        *读表状态=.t.
    ELSE
        *读表状态=.f.   
    ENDIF
ENDIF
25 回复
#2
laowan0012022-06-12 09:57
这段程序是timer里的吗?如果是的话,间隔是多少?

*每天23时为水表日结算时刻,数据初始化
IF HOUR(当前时间)=23&& AND MINUTE(当前时间)=59 AND SEC(当前时间)=59   
if语句中的“&&”把后面的判断给注释掉了,应该是从23:00:00开始到23:59:59之间都执行这段代码
而且,这里更改了上报状态:上报状态=.F.,但是没有地方改成.T.
猜想“上报状态”是个变量(不是字段),在thisform.上报()里更改为.T.了

没看出明显的问题来,如果问题发生在23:59:59之后,可以检查一下那两条Insert语句是否正常工作了
建议:程序中有4个条件判断,之间没有关联关系,可以使用case分支处理
#3
Pgwyg2022-06-12 10:05
timer的时间间隔是1000毫秒,insert正常,TRY未能捕捉错误
#4
吹水佬2022-06-12 10:58
1、定时器(Timer)不“定时”,计时精度有可能不能达到要求,造成不能准时执行任务。
2、“程序无响应”未必是定时器本身的问题,可以在定时器事件中只用一句 INKEY(0.001) 测试。

#5
Pgwyg2022-06-12 11:23
读水表远程上报程序,有时运行几天没问题,有时一天就没响应,但是时间就是19点和23点这两个时间段,其他时间没问题,不写数据库也会出现问题。
#6
laowan0012022-06-12 11:46
把timer的间隔改成800试试
#7
laowan0012022-06-12 11:47
不好找的问题可以考虑在本地建立日志(一个DBF),每个关键点或动作都记录一条,看看在哪里就停止了
#8
吹水佬2022-06-12 11:54
这样试试:
** Timer 事件
this.Enabled = .F.
INKEY(0.001)
...... 事务过程
this.Enabled = .T.
#9
Pgwyg2022-06-12 12:11
试过了,不灵
#10
Pgwyg2022-06-12 12:12
关键是两个时间点让人费解
#11
Pgwyg2022-06-12 12:18
手机版不能截屏
#12
Pgwyg2022-06-12 15:17
timer控件初始化在表单INIT事件中,代码如下:
Do while .t.
If sec(datetime())=int(sec(datetime()))
Thisform.timer1.interval=1000
Thisform.timer1.reset
Thisform.timer1.enabled=.t.
Exit
Endif
Enddo
延时程序是这样的:
Function wait_time
Lparameter  x_time
Do while second()>x_time
Enddo
Return .t.
Endfnc

使用inkey()或wait光标随意乱闪,看着不舒服
#13
吹水佬2022-06-12 17:37
以下是引用Pgwyg在2022-6-12 12:12:48的发言:

关键是两个时间点让人费解

暂不要处理数据,先排除“挂死”的问题,要花点时间测试。
如果一定要用timer,也可以试试异步消息来处理。因timer消息优先级很低,且timer事件过程也有时限,timer事件过程执行并不是那么稳定。
异步消息处理过程:自定义一个窗口消息事件过程,timer事件触发时暂停timer事件并PostMessage自定义窗口消息,在自定义窗口消息事件过程执行数据处理,数据处理完毕继续启动timer事件。
“挂死”的问题解决了就好办,其他问题就是时间控件问题。
最好不要用timer来做实时监控,不太精准稳定可靠。
可以考虑用多进程来处理
#14
laowan0012022-06-12 18:07
If sec(datetime())=int(sec(datetime()))
这个条件好像肯定是.T.吧?

另外,正如吹版所言,由于种种原因,timer中的执行过程所需时间并不确定,执行所需时间超过间隔时间的时候会造成timer过程未完成,下一次timer又触发了
我习惯的做法:timer过程中,首先this.enable=.F.,然后执行程序,执行完毕后this.enable=.T.。或者再加一句this.reset(注意程序中如果有条件退出或中断时,别忘了this.enable=.T.)
#15
mywisdom882022-06-13 08:47
方法不是很好,你的方法理论上可以,但由于定时器问题导致。
解决方法,用变量,判断,时间相减,应该可以
用1个全程变量,t更新时间,

public t更新时间
t更新时间 = datetime()

** Timer 事件
if datetime()-t更新时间 >=3600 && 3600秒,1小时
   t更新时间 = datetime() && 重新保存时间
   * 做你更新的程序
endif
#16
mywisdom882022-06-13 08:56
这样做,利用时间差,判断上次更新时间与当前时间,只要超过1小时,就更新,同时保存上次更新时间,要先保存更新时间,就算定时器,怎么不灵活,也会 0.1秒触发1次。
当然,加上开关,可能会比较好


public t更新时间
t更新时间 = datetime()

** Timer 事件
if datetime()-t更新时间 >=3600 && 3600秒,1小时
   t更新时间 = datetime() && 重新保存时间
   this.Enabled = .F.
   * 做你更新的程序
   this.Enabled = .T.
endif
#17
Pgwyg2022-06-13 09:39
回复 16楼 mywisdom88
谢谢您,我需要整点保存数据,而且要有时间显示,原来使用一个timer实现时间同步显示、实时数据采集、和数据保存,出现问题后又添加了一个专门负责数据采集,还是出现程序无响应的问题,即使停止数据采集工作,也是这样,现在又加了一个计时器,专门负责时间显示,看看能否成功。百思不得其解的是有时工作几天没问题,一旦出现问题,就是停在19:59:59和23:59:59,如果随机还好理解。TYR也未能捕捉到错误。
TRY
DO FORM YCCB2
READ EVENTS        
CATCH TO ex
        ex_info= "错误编号: "+ALLTRIM(STR(ex.ErrorNo))+CHR(10)+CHR(13)+;
        "    错误行号: "+ALLTRIM(STR(ex.LineNo))+CHR(10)+CHR(13)+;
        "    错误信息: "+ALLTRIM(ex.Message)+CHR(10)+CHR(13)+;
        "    错误函数: "+ALLTRIM(ex.Procedure)+CHR(10)+CHR(13)+;
        "    错误细节: "+ALLTRIM(ex.Details)+CHR(10)+CHR(13)+;
        "调用堆栈级别: "+ALLTRIM(STR(ex.StackLevel))+CHR(10)+CHR(13)+;
        "  代码行内容: "+ALLTRIM(ex.LineContents)
        StrToFile(ex_info, "d:\error_info.txt")
ENDTRY
#18
厨师王德榜2022-06-13 10:07
类似问题我以前遇到过,当时在vfp平台上,也没有很好地解决,后来采用变通的方式解决的 .
我的解决方式为:
利用SqlServer服务器上的定时任务,运行事先写好存储过程解决的.
也就是说,不是在vfp平台上解决的.
#19
mywisdom882022-06-13 11:16
以下是引用Pgwyg在2022-6-13 09:39:44的发言:

谢谢您,我需要整点保存数据,而且要有时间显示,原来使用一个timer实现时间同步显示、实时数据采集、和数据保存,出现问题后又添加了一个专门负责数据采集,还是出现程序无响应的问题,即使停止数据采集工作,也是这样,现在又加了一个计时器,专门负责时间显示,看看能否成功。百思不得其解的是有时工作几天没问题,一旦出现问题,就是停在19:59:59和23:59:59,如果随机还好理解。TYR也未能捕捉到错误。
TRY
DO FORM YCCB2
READ EVENTS        
CATCH TO ex
        ex_info= "错误编号: "+ALLTRIM(STR(ex.ErrorNo))+CHR(10)+CHR(13)+;
        "    错误行号: "+ALLTRIM(STR(ex.LineNo))+CHR(10)+CHR(13)+;
        "    错误信息: "+ALLTRIM(ex.Message)+CHR(10)+CHR(13)+;
        "    错误函数: "+ALLTRIM(ex.Procedure)+CHR(10)+CHR(13)+;
        "    错误细节: "+ALLTRIM(ex.Details)+CHR(10)+CHR(13)+;
        "调用堆栈级别: "+ALLTRIM(STR(ex.StackLevel))+CHR(10)+CHR(13)+;
        "  代码行内容: "+ALLTRIM(ex.LineContents)
        StrToFile(ex_info, "d:\error_info.txt")
ENDTRY

整点,和差几秒,有区别吗,我说的时间差,是可以做到相差几秒处理的。
19:59:59,就是20点,那你在20:00:01~20:00:05秒处理,应该可以吧
#20
mywisdom882022-06-13 11:19
你处理时间,相差1秒,都不可以的话,在VFP中的定时器处理,有点难,你用18楼的方法看看,就算是18楼的方法,你电脑时间也会出现几秒的时间差
#21
吹水佬2022-06-13 11:58
IF MINUTE(当前时间)=0 AND sec(当前时间)=0 &&
IF HOUR(当前时间)=23&& AND MINUTE(当前时间)=59 AND SEC(当前时间)=59
在timer用相等比对有可能会“错失时机”而达不到要求,如:
sec(当前时间)=0
SEC(当前时间)=59
#22
mywisdom882022-06-13 12:38
肯定是会错过,所以不能用 =

#23
my23182022-06-13 13:55
以下是引用Pgwyg在2022-6-13 09:39:44的发言:

谢谢您,我需要整点保存数据,而且要有时间显示,原来使用一个timer实现时间同步显示、实时数据采集、和数据保存,出现问题后又添加了一个专门负责数据采集,还是出现程序无响应的问题,即使停止数据采集工作,也是这样,现在又加了一个计时器,专门负责时间显示,看看能否成功。百思不得其解的是有时工作几天没问题,一旦出现问题,就是停在19:59:59和23:59:59,如果随机还好理解。TYR也未能捕捉到错误。
TRY
DO FORM YCCB2
READ EVENTS        
CATCH TO ex
        ex_info= "错误编号: "+ALLTRIM(STR(ex.ErrorNo))+CHR(10)+CHR(13)+;
        "    错误行号: "+ALLTRIM(STR(ex.LineNo))+CHR(10)+CHR(13)+;
        "    错误信息: "+ALLTRIM(ex.Message)+CHR(10)+CHR(13)+;
        "    错误函数: "+ALLTRIM(ex.Procedure)+CHR(10)+CHR(13)+;
        "    错误细节: "+ALLTRIM(ex.Details)+CHR(10)+CHR(13)+;
        "调用堆栈级别: "+ALLTRIM(STR(ex.StackLevel))+CHR(10)+CHR(13)+;
        "  代码行内容: "+ALLTRIM(ex.LineContents)
        StrToFile(ex_info, "d:\error_info.txt")
ENDTRY

整点是一个时刻,而程序处理所有数据需要一段时间吧,是一个时间段,只保存整点数据,这是一个逻辑悖论。应该像几位版主说的,整点附近的时间段数据可以看做整点时的数据,这样处理起来就简单方便了。如果是我做,就在整点开始保存所有数据。这点可以参考月底手机流量的记录方法,当然我说的是三大公司,不是个体手机。
#24
Pgwyg2022-06-14 09:02
按照7楼的思路创建了一个日志,只保留日志功能,删除TIMER事件中的其他过程
程序如下:
*Timer1控件interval=500
*Timer1控件Timer事件
*
当前时间=DATETIME()
*显示时间
this.Enabled=.f.
IF thisform.timexs.Caption!=TTOC(当前时间)
    更新时间显示
    thisform.timexs.Caption=TTOC(当前时间)
ENDIF
*整点(每60分钟)保存一次数据
IF MINUTE(当前时间)=0 AND sec(当前时间)=0
    INSERT INTO DATA\TEST_DATA (TIME_T) VALUES (当前时间)
    thisform.label1.CAPTION=TTOC(当前时间)+" 的数据已经保存! "   
ENDIF
this.Enabled=.t.
运行结果
第一天早上9点开始运行,每小时保存一次数据,日志上显示最后一条数据是19:00:00,但是thisform.label1.CAPTION显示20点、21点、22点、23点的数据已经保存,实际上数据并没有保存!
thisform.timexs.Caption控件最后显示为23:59:59,程序无响应,使用任务管理器强制退出。
问题出在那里?


[此贴子已经被作者于2022-6-14 09:05编辑过]

#25
sostemp2022-06-14 09:38
上传示例来测试吧
#26
laowan0012022-06-14 11:06
这台机器除了这个任务,还执行其他什么任务吗?
1