当前位置:主页>销售管理软件> 列表

真诚要请你来指正我程序不足之处,提出有效建议者,20分赠送 找会计电算化软件下载

库存管理软件版1楼: 软件编写的背景是,电台的频率接受机需要实现在某个时间段接受一个频率定值,这个定值的误差在+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;

//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 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;


procedure TScanThread.Execute;
{********************扫描接受机端口的线程的执行函数****************************}
begin
while true do
begin
try
//criticalsection.Enter;
synchronize(scandataD);
synchronize(scandataR);
synchronize(comparedata);

sleep(500);
// criticalsection.Leave;
except
showmessage(''接收机错误'');
exit;
end;//try
end;//while
end;//procedure


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;//if

end;//procedure


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
begin

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 7 do
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 orSND_NODEFAULT);
//记住上面使用wave类型资源文件的方法
//abort;
end
else
begin
exit;
end;
except
abort;
end; //end try
end
else
begin
shape.Brush.Color:=clLime;
end;//end if i>5

end;//procedure

initialization
//criticalsection:=Tcriticalsection.Create;

end.





unit UnitthreadE;

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


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,unitthreadR,unitthreadG;

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


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

create(createsuspend);

freeOnTerminate:=true;
Priority:=tpnormal;
end;


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


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


initialization
//criticalsection:=Tcriticalsection.Create;

end.




unit UnitthreadG;

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


TScanthreadG=class(TThread)
{************派生线程扫描GPS*************}
private
NeonumledG:TNeonumled;
commG:TMSComm;
portnumG : integer;

procedure ScanDataG;

protected
procedure Execute;override;

public
//扫描GPS线程的构造函数
constructor create( createsuspend:boolean;
AcommG:TMSComm; //GPS端口控件
ANeonumledG:TNeonumled; //显示GPS时间
AportnumG:integer //GPS端口号
);
overload;

end;

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

implementation

uses

unitmain,unitthreadR,unitthreadE;

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;


procedure TScanThreadG.Execute;
{********************扫描GPS端口的线程的执行函数*******************************}
begin
//criticalsection1.Enter;
while true do
begin
try
synchronize(scandataG);
sleep(200);
except
showmessage(''GPS err!'');
eixt;
end; //try

end; //while
//criticalsection1.Leave;

end;//procedure


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;//if
end;//procedure

initialization
//criticalsection:=Tcriticalsection.Create;

end.

2楼: 大家可以随便拍砖,无论怎样批评,我都将不胜荣幸,如果能够提出能够使本程序得到重大改进建议者,我将倾我所有酬谢!! 如会计电算化软件下载

3楼: 审阅完毕,不知所云。

4楼: 首先希望得到大家关于程序本身结构问题的意见,
以上是我程序里线程的三个单元
我一直觉得线程构造函数参数太多了,不知道有没有大侠能帮忙解决一下

5楼: 代码无法测试,所以就正确性来说不得而知。仅从编程风格来说比较中庸,基本是顺着思路一路写下来,建议重构。对于线程构造函数参数太多的问题的确是这样,建议仿照VCL写个CustomXXX Class在从这个Class inherited暴露一些必要的接口,其实三个Thread有一些共同的方法和属性,不过是功能不同罢了。建议写Interface在进一步用Thread来实现,这样有比较统一完善的调度过程。呵呵,代码没细看,不足之处请批评指正

6楼: 非常感谢Rainstorey,kinneng给的点评,


由于我水平有限,所以一直不能有所改进,
Rainstorey给我提供很好的改进建议,尤其是使用接口技术,非常的感谢,

衷心希望各位高手继续给小弟拍砖,不胜感激,小分一点聊表谢意!!

库存管理软件版7楼: 多人接受答案了。