对本人程序提出有益批评&建议者,50分跪送!!!! ( 积分: 50 )

  • 主题发起人 主题发起人 zhaokaien
  • 开始时间 开始时间
Z

zhaokaien

Unregistered / Unconfirmed
GUEST, unregistred user!
这个软件是给石家庄九五一电台编写的频率监控软件,软件编写的背景是,九五一电台的频率接受机需要实现在某个时间段接受一个频率定值,这个定值的误差在+5(可调),如果超过该范围,就会导致电台停播,这对于电台来讲是重大事故,所以必须对频率值进行监控,并对出错情况进行相应的处理。

我编写的这个软件针对需求主要分三个模块:
(1)从gps获得相关数据,如精确到秒的时间值
(2)提供界面让工作人员可以随时将预定时间段的预设值写入数据库;监控接受机端口接收到的频率值,并扫描数据库,然后将频率值与从数据库中读取的预设值进行比对,如果超过误差范围,进行报警。
(3)向数据库中写入相关错误信息供工作人员查看。

软件整体使用了多线程,从Tthread派生了三个类,比对报警线程类,读GPS线程类,写错误日志线程类,
相关代码都在前面的程序单元里,里面也有相关构造函数参数的相关注释

对您的审阅表示感谢,如能得到你的指点,将不胜荣幸!
 
这个软件是给石家庄九五一电台编写的频率监控软件,软件编写的背景是,九五一电台的频率接受机需要实现在某个时间段接受一个频率定值,这个定值的误差在+5(可调),如果超过该范围,就会导致电台停播,这对于电台来讲是重大事故,所以必须对频率值进行监控,并对出错情况进行相应的处理。

我编写的这个软件针对需求主要分三个模块:
(1)从gps获得相关数据,如精确到秒的时间值
(2)提供界面让工作人员可以随时将预定时间段的预设值写入数据库;监控接受机端口接收到的频率值,并扫描数据库,然后将频率值与从数据库中读取的预设值进行比对,如果超过误差范围,进行报警。
(3)向数据库中写入相关错误信息供工作人员查看。

软件整体使用了多线程,从Tthread派生了三个类,比对报警线程类,读GPS线程类,写错误日志线程类,
相关代码都在前面的程序单元里,里面也有相关构造函数参数的相关注释

对您的审阅表示感谢,如能得到你的指点,将不胜荣幸!
 
unit UnitThread;
interface
uses
Windows,Classes,Graphics,MSCommLib_TLB,DB, ADODB,NeoNumLED,dateutils,SysUtils,syncobjs,StdCtrls,dialogs,ExtCtrls,MMSystem;
//引入Mscomm控件的时候,Mscommlib_tlb不能少
//使用showmessage函数的时候,dialogs不能少
//使用数据库控件时,DB,ADODB不能少
//使用日期函数如DecodeDateTime时,dateutils不能少
//使用now函数时,sysutils不能少
//使用criticalsection时syncobjs不能少
//使用Tedit时,StdCtrls不能少
//使用Tshape时,ExtCtrls不能少
//使用Tshape的颜色值时,Graphics不能少
type
TScanThread = class(TThread)
{************派生线程扫描接收机*************}
private
Rnum:string;
shape:Tshape;
table:string;
NeonumledR,NeonumledD,NeonumledC:TNeonumled;
portnumR,portnumG:integer;
commR:TMSComm;
query:TADOQuery;
procedure ScanDataR ;//扫描接收机
procedure ScanDataD;//扫描数据库
procedure comparedata;//比较
protected
procedure Execute;
override;
public
constructor create(createsuspend:boolean;//create flag
AcommR:TMSComm;//接收机端口控件
Aquery:TAdoquery;//扫描数据库预设值
ANeonumledR:TNeonumled;//显示预设值
ANeonumledC:TNeonumled;//显示频率差
ANeonumledD:TNeonumled;//显示实际频率
Atable:string;//预设值所在数据库
AportnumR:integer;//接收机端口号
Ashape:Tshape;//报警信号标志
ARnum:string);//接收机号
overload;
end;

TScanthreadG=class(TThread)
{************派生线程扫描GPS*************}
private
NeonumledG:TNeonumled;
commG:TMSComm;
portnumG : integer;
procedure ScanDataG;
protected
procedure Execute;override;
public
constructor create(createsuspend:boolean;
AcommG:TMSComm;//GPS端口控件
ANeonumledG:TNeonumled;//显示GPS时间
AportnumG:integer);//GPS端口号
overload;
end;

TScanThreadE=class(TThread)
{************派生线程写错误日志*************}
private
queryerr:TADOQuery;
procedure writeerr;
protected
procedure Execute;
override;
public
constructor create(createsuspend:boolean;
Aqueryerr:TAdoquery);//向数据库写入错误日志
overload;
end;

//errnum=(y = 1,e = 2,s = 3,ss = 4,w = 5,l = 6,q = 7,b = 8);

implementation
uses unitmain;
var
//flag:array of boolean;
//criticalsection,criticalsection1:Tcriticalsection;
facttime,errfre,yushefre:string;
errnum:string;
weekflag:word;
i:integer;
n:integer;


constructor TScanThreadG.create(createsuspend:boolean;AcommG:TMSComm;ANeonumledG:TNeonumled;AportnumG:integer);
{********************扫描GPS端口的线程的构造函数*******************************}
begin
NeonumledG:=ANeonumledG;
portnumG:=AportnumG ;
commG:=AcommG;
create(createsuspend);
freeOnTerminate:=true;
Priority:=tptimecritical;
end;


constructor TScanThread.create(createsuspend:boolean;AcommR:TMSComm;Aquery:TAdoquery;
ANeonumledR:TNeonumled;ANeonumledC:TNeonumled;ANeonumledD:TNeonumled;Atable:string;AportnumR:integer;Ashape:Tshape;ARnum:string);
{********************扫描接受机端口的线程的构造函数*******************************}
begin
create(createsuspend);
Rnum:=ARnum;
shape:=Ashape;
commR:=AcommR;
query:=Aquery;
NeonumledR:=ANeonumledR;
NeonumledC:=ANeonumledC;
NeonumledD:=ANeonumledD;
table:=Atable;
portnumR:=AportnumR;
freeOnTerminate:=true;
end;

constructor TScanThreadE.create(createsuspend:boolean;Aqueryerr:TAdoquery);
{********************写错误日志的线程的构造函数*******************************}
begin
queryerr:=Aqueryerr;
create(createsuspend);
freeOnTerminate:=true;
Priority:=tpnormal;
end;



procedure TScanThreadG.Execute;
{********************扫描GPS端口的线程的执行函数*******************************}
begin
//criticalsection1.Enter;
while truedo
begin

try
synchronize(scandataG);
sleep(200);
except
showmessage('GPS err!');
eixt;
end;

end;
//criticalsection1.Leave;
end;

procedure TScanThread.Execute;
{********************扫描接受机端口的线程的执行函数*******************************}
begin
while truedo
begin
try
//criticalsection.Enter;
synchronize(scandataD);
synchronize(scandataR);
synchronize(comparedata);
sleep(500);
// criticalsection.Leave;
except
showmessage('接收机错误');
exit;
end;
//try
end;

end;

procedure TScanThreadE.Execute;
{********************写错误日志的线程的执行函数*******************************}
begin
while truedo
begin
try
synchronize(writeerr);
sleep(500);
except
showmessage('写入日志错误');
exit;
end;
//try
end;
//while
end;

procedure TScanThreadE.writeerr;
{********************写错误日志*******************************}
begin
if (i>5) then
//如果频率差大于5,写日志
begin
queryerr.SQL.Clear;
queryerr.SQL.Text:='insert into errlogo values (:errtime,:reiceivenum,:yushefre,:errfre,:memo)';
queryerr.Parameters.ParamByName('reiceivenum').Value:=errnum;
queryerr.Parameters.ParamByName('errtime').Value:=strtodatetime(facttime);
queryerr.Parameters.ParamByName('yushefre').Value:=yushefre;
queryerr.Parameters.ParamByName('errfre').Value:=errfre;
if strtoint(errfre)=0 then
begin
queryerr.Parameters.ParamByName('memo').Value:='接收机无接收数据';
end
else
begin
queryerr.Parameters.ParamByName('memo').Value:='频率值不正确';
end;

queryerr.ExecSQL;
queryerr.Close;
end;
//if first
end;

procedure TScanThread.ScanDataR;
////////////////////////////////////////扫描接收机端口频率值///////////////////////////////
var
Rdata:olevariant;
Rstr:string;
begin
{扫描接收机}
commR.CommPort:=portnumR;
commR.InBufferSize:=1024;
commR.OutBufferSize:=512;
commR.InBufferCount:=0;
commR.OutBufferCount:=0;
commR.Settings:='9600,n,8,1';
commR.RThreshold:=128;
commR.InputLen:=0;
if commR.CommEvent=comEvReceive then
begin
try
Rdata:=commR.Input;
Rstr:=Rdata;
//接受接收机端口数据,这里还要添加相应的处理数据的程序
NeonumledR.Text:=Rstr;
errfre:=Rstr;

if Rdata='' then
begin
showmessage('端口无数据');
abort;
end;

except
showmessage('数据接受失败!');
abort;
end;
//try
end
else

begin
NeonumledR.Text:='0';
errfre:='0';
end;

end;

procedure TScanThreadG.ScanDataG ;
//////////////////////////////////扫描GPS端口时间值///////////////////////////////////
var
Gdata:olevariant;
Gstr:string;
y,m,d,h,min,sec,milisec,weekofyear,dayofweek:WORD;
years,mons,days,hours,minutes,seconds,miliseconds,weeks:string;
begin
{扫描GPS}
commG.CommPort:=portnumG;
commG.InBufferSize:=1024;
commG.OutBufferSize:=512;
commG.InBufferCount:=0;
commG.OutBufferCount:=0;
commG.Settings:='9600,n,8,1';
commG.RThreshold:=128;
commG.InputLen:=0;
if commG.InBufferCount<>0 then
begin
{取GPS时间}
if commG.CommEvent=comEvReceive then
begin

try
Gdata:=commG.Input;
Gstr:=Gdata;
if Gdata='' then
begin
showmessage('GPS端口无数据!');
end;

except
showmessage('GPS数据接收失败!');
abort;
end;
//try
end;

NeonumledG.Text:=Gstr;
facttime:=Gstr;
end
else

begin

try
{取系统时间}
Decodedatetime(now,y,m,d,h,min,sec,milisec);
Decodedateweek(now,y,weekofyear,dayofweek);
weekflag:=dayofweek+3;
case dayofweek of
1:
weeks:='星期一';
2:
weeks:='星期二';
3:
weeks:='星期三';
4:
weeks:='星期四';
5:
weeks:='星期五';
6:
weeks:='星期六';
7:
weeks:='星期天';
end;

years:=inttostr(y);
mons:=inttostr(m);
days:=inttostr(d);
hours:=inttostr(h);
minutes:=inttostr(min);
seconds:=inttostr(sec);
miliseconds:=inttostr(milisec);
NeonumledG.Text:=years+'-'+mons+'-'+days+' '+hours+':'+minutes+':'+seconds ;
facttime:=years+'-'+mons+'-'+days+' '+hours+':'+minutes+':'+seconds ;
except
showmessage(' 系统时间获取失败');
exit;
end;
//try
end;

end;
//over

procedure TScanThread.ScanDataD;
////////////////////////////////////////////扫描数据库预设值//////////////////////////////////////////
begin
{扫描数据库}
query.SQL.Clear;
query.SQL.text:='select * from '+ table+' where (:settime between 开始时间 and 结束时间) and(发射机号='+''''+Rnum+''''+')';
if facttime<>'' then
begin
{拿当前时间和数据库中预设时间段进行比较}
query.Parameters.ParamByName('settime').Value:=strtodatetime(facttime);
end
else
begin
showmessage('无时间值');
abort;
//terminate,exit,abort中,经过试验得出的结论是,abort能
//退出到程序(暂时不执行线程)外,效果最强
end;

query.open;
if query.Fields.Fields[weekflag].Value=true then
begin
if query.Fields.Fields[1].asstring<>'' then
//数据库里的预设频率值是否为零
begin
NeonumledD.Text:=query.Fields.Fields[1].asstring;
yushefre:=query.Fields.Fields[1].asstring;
end
else
begin
NeonumledD.Text:='0';
end;
end
else
if query.Fields.Fields[weekflag].Value=false then
{判断星期的标志}
begin
if query.Fields.Fields[1].asstring<>'' then
begin
NeonumledD.Text:='0';
NeonumledR.Text:='0';
NeonumledC.Text:='0';
end;
end
else
//如果星期为nil值,即没有符合扫描条件数据值时
begin
NeonumledD.Text:='0';
end;
//以上的逻辑是:如果星期标志设置,那么看扫到纪录的预设频率值相,若频率值非空,此值为预设频率值
end;
//end procedure

procedure TScanThread.comparedata;
//////////////////////////////////////比较预设值与实际值,并进行相应处理///////////////////////////////
var
soundstr:string;
soundnum:string;
begin
i:=strtoint(NeonumledD.Text)-strtoint(NeonumledR.Text);
//数据库预设置-实际频率值
NeonumledC.Text:=inttostr(i);
if i>5 then
//如果频率差大于5 ,进行相应的处理
begin
shape.Brush.Color:=clRed;
errnum:=rnum;//保存错误接收机号 ,rnum是从构造函数赋值的
if errnum='一号机' then
begin
soundnum:='1.wav';
end
else
if errnum='二号机' then
begin
soundnum:='2.wav';
end
else
if errnum='三号机' then
begin
soundnum:='3.wav';
end
else
if errnum='四号机' then
begin
soundnum:='4.wav';
end
else
if errnum= '五号机' then
begin
soundnum:='5.wav';
end
else
if errnum='六号机' then
begin
soundnum:='6.wav';
end
else
if errnum='七号机' then
begin
soundnum:='7.wav';
end
else
if errnum='八号机' then
begin
soundnum:='8.wav';
end
else
begin
showmessage('找不到声音文件');
exit;
end;

{if errnum='一号机' then
begin
flag[0]:=true;
end
else
if errnum='二号机' then
begin
flag[1]:=true;
end
else
if errnum='三号机' then
begin
flag[2]:=true;
end
else
if errnum='四号机' then
begin
flag[3]:=true;
end
else
if errnum='五号机' then
begin
flag[4]:=true;
end
else
if errnum='六号机' then
begin
flag[5]:=true;
end
else
if errnum='七号机' then
begin
flag[6]:=true;
end
else
if errnum='八号机' then
begin
flag[7]:=true;
end
else
begin
for n:=0 to 7do
begin
flag[n]:=false;
end;
//for
end;
}
try
if query.Fields.Fields[11].asstring<>''then
begin
if fileexists(query.Fields.Fields[11].asstring) then
begin
soundstr:=query.Fields.Fields[11].asstring;
end
else
begin
soundstr:=extractfilepath(paramstr(0))+'/res/'+ soundnum;
end;
mciexecute(pchar('play '+soundstr));
{播放报警声音}
//注意这里不能使用playsound或者snplaysound,不然这里的播放效率会非常低
//而且有可能 造成死机
// PlaySound(Pansichar('1wave'),hinstance ,SND_RESOURCE or SND_NODEFAULT);
//记住上面使用wave类型资源文件的方法
// abort;
end
else

begin

exit;
end;

except
abort;
end;
//end try

end //end if i>5
else

begin
shape.Brush.Color:=clLime;
end;

end;
//over

initialization
//criticalsection:=Tcriticalsection.Create;

end.
 
真诚希望能得到大家的批评指正,就算是对我的编程风格提出批评,都将赠分
不论怎样批评我都可以接受,
谢谢大家了!!!!!!!!!!!
 
呵呵,那我就说说你的编码风格吧。说得不对请海涵呀。
看了你的代码,不知道你写完代码以后如何实现ROSE逆向?
也就是说看你的代码风格,你在实现ROSE逆向的时候,逆向的方法,参数说明很难生成的吧。
你这样写试一试:
public
//这里书写你的函数的功能说明
function MyFun(//第一次参数说明
x:Integer;
//第二个参数说明
str:String):Boolean;
这样你在使用ROSE逆向的时候会将你的函数说明和参数说明直接逆向成功。
 
我直说了,代码写的不规范,个人意见
 
谢谢上面两位,我想请教fxh7622,rose逆向我不懂,
我得程序调试运行很正常啊,
还有sbzldlb,能否给我示范一下规范的代码形式,谢谢两位了
 
呵呵,我没有说你的代码运行不正常,只是说你在使用ROSE逆向的时候,依你上面的编码风格,无法将函数说明,参数说明直接逆向出来的!
 
fxh7622,我还是不太懂,请问能跟我说一下解决方法吗,怎么才能 很清楚地表达那 ,事实上,我也觉得我得构造函数的参数表台乱,但是以我现在地水平想不出更好的解决方法
昨天下班了,实在不好意思
 
一个类放在一个单元文件里面嘛
 
不要挑那么多了,其实有多少人写的代码规范?当然编程规范是一个好习惯,但是这个是慢慢培养和锻炼的。能够做出来说明问题解决了,然后在慢慢的规范代码吧。如果真的说你程序的不足吧,第一,线程中使用太多的sleep了,尽量少使用,第二,有的条件判断没有必要在另外一个函数里面进行,比如下面这段代码:
procedure TScanThreadE.writeerr;
{********************写错误日志*******************************}
begin
if (i>5) then
//如果频率差大于5,写日志
begin
queryerr.SQL.Clear;
queryerr.SQL.Text:='insert into errlogo values (:errtime,:reiceivenum,:yushefre,:errfre,:memo)';
queryerr.Parameters.ParamByName('reiceivenum').Value:=errnum;
queryerr.Parameters.ParamByName('errtime').Value:=strtodatetime(facttime);
queryerr.Parameters.ParamByName('yushefre').Value:=yushefre;
queryerr.Parameters.ParamByName('errfre').Value:=errfre;
if strtoint(errfre)=0 then
begin
queryerr.Parameters.ParamByName('memo').Value:='接收机无接收数据';
end
else
begin
queryerr.Parameters.ParamByName('memo').Value:='频率值不正确';
end;

queryerr.ExecSQL;
queryerr.Close;
end;
//if first
end;
你的if i>5 then
这个完全可以放在execute中来处理,这样就不用每次都调用上面这个函数才进行判断了,从内存处理上来说,是不是就不用把上面的函数调入了呢?
对了,我写代码也很难的,不好意思。你的软件运行没有问题,但是估计有时候你会感觉有点响应迟钝。
 
赞同royal1442说得,一个类放到一个文件单元里,这样会显得很清晰
cqwty,说得也很有道理,一个函数尽可能要简洁,不要超过25行
fxh7622说的我现在有点明白了,
金玉良言,谢谢了,我想对于大家都有启示,希望大家再多多提出更多的好规范

另外有人看出程序在质量上有什么大问题吗,比如exception机制是否合理等
 
大家不要客气,请大家尽量拍砖,
怎么批评我都可以接受。。。
 
cqwty,我得程序没有响应迟钝的问题,最初的时候 我使用snplaysound播放报警声音,出现过迟钝的情况,但后来我改成用mci的mcisendstring后一点问题都没有了,现在程序运行很正常,但我觉得需要更进一步的改进,谢谢你
 
我听说每个涉及到ado的线程最好每个线程都建一个连接,但是现在我的程序好像没有什么问题,不知道 这种看法是否正确,我有必要为每一个线程都加上对应的连接吗??
会不会太冗余了
 
構造函數參數太多了:-(,若是要修改或增加一個參數,就。。。
建議使用工廠模式
 
我也觉得是这样,请教能说的更详细一点吗,非常非常的感谢
 
对于模式这一块我真的一点概念都没有,倒是看到国一些文章,没有深究过
 
非常希望能得到您的指教,
谢谢了
 
至于ado方面的多线程,我还是主张一个线程一个connection,这样比较好,对于资源上来说,如果你的线程虽然运行了,但是没有数据的交换,一般占用不了多少资源的。个人看法。
 
后退
顶部