一般来说,应该没问题,但是,Delphi 中的 TThread 线程类,实际上是 自己创立一个 Form 用来实现对 VCL 的线程级的安全调用。 可能问题就是出现在这里了,至于怎么解决,我也不太清楚 (我刚学delphi不久),你可以尝试在线程中释放时间段,也许会有用。 use API function: Sleep(...) or use delphi function ProcessMessage;
再看看我改成这样了: clientsock = class(TThread) private Client:Tsocket; N:integer; Procedure Timerun(N:integer); { Private declarations } protected procedure Execute; override; Public constructor Create(FT:Boolean;{port,}IP:string;CN:integer); end; Procedure Clientsock.Timerun(N:integer); const BlockLen=1024*4; var s: array[0..BlockLen-1] of byte; z:byte; st,st1,ls_ic:string; r,i,j,K:integer; evttime:Tdatetime; begin r:=recv(Client,s,BlockLen,0) ; //收到的字节数 if r=0 then exit ; if Ft[N]=0 then begin if s[0]=38 then //收到& begin F_main.Edits[N].Text :=Lock_id[N]+'巡检握手成功'; F_main.Edits[N].Refresh ; //写日制文件 F_main.File_today('巡检握手成功Client'+IntTostr(N)); s_time[N]:=FormatDateTime('YYYYMMDDHHMM',now()); xor_time[N]:=F_main.Compute_xor(s_time[N]); //计算时间密钥 F_main.Sic_com('L06'+s_time[N]+xor_time[N],12,0); Send(Client,F_main.Dsic[N],9,0); //发送巡检 F_main.Edits[N].Text :=Lock_id[N]+'巡检发送时间'; F_main.Edits[N].Refresh ; Ft[N]:=Ft[N]+1; end; end else begin if Ft[N]>3 then begin F_main.Memo1.Lines.Add(Lock_id[N]+'重发三次错误,锁可能故障,请检查锁状态1'); closeSocket(Client); F_main.Client_Close(N); //写日制文件 F_main.File_today(Lock_id[N]+'巡检失败Client'+IntTostr(N)); Terminate; F_octem.sock_xj;//判断巡检结束没有 exit; end else begin //判断接收正确 j:=s[0]; for i:=1 to r-1 do begin j:=j xor s[i]; end; if j<>0 then begin z:=37; //% //写日制文件 F_main.File_today(Lock_id[N]+'巡检接收错误sock'+IntTostr(N)); Send(Client,z,1,0); F_main.Edits[N].Text :=Lock_id[N]+'巡检重发'; F_main.Edits[N].Refresh ; Ft[N]:=Ft[N]+1; end else if j =0 then begin z:=36; //$ Send(Client,z,1,0); //写日制文件 F_main.File_today(Lock_id[0]+'巡检接收正确'); F_main.Memo1.Lines.Add('锁巡检正确锁号:'+Lock_id[N]); closeSocket(Client); F_main.Client_Close(N); //把Byte转成string for i:=0 to (r-1) do begin if s[i]=10 then st:=st+'a' else if s[i]=11 then st:=st+'b' else if s[i]=12 then st:=st+'c' else if s[i]=13 then st:=st+'d' else if s[i]=14 then st:=st+'e' else if s[i]=15 then st:=st+'f' else st:=st+char(s[i]); // end; //写日制文件 F_main.File_today(Lock_id[N]+'巡检接收正确sock '+IntTostr(N)+st); for k:=1 to (r-4)div 20 do begin st1:=copy(st,3+(k-1)*20,20); evttime:=StrToDatetime(copy(st1,1,4)+'-'+copy(st1,5,2)+'-'+copy(st1,7,2)+' '+copy(st1,9,2)+':'+copy(st1,11,2)); ls_ic:=copy(st1,13,8); F_main.Insert_ofdevtlog(Lock_id[N],evttime,'0',ls_ic); end; Terminate; //if F_octem.T[1]=0 then Terminate; if not F_octem.Li then F_octem.sock_xj;//判断巡检结束没有 end; end; end; end;
接上: procedure clientsock.Execute; begin while not Terminated do begin Application.ProcessMessages ; if F_octem.T[0]>0 then Timerun(0);; if F_octem.T[1]>0 the Timerun(1); end; end; constructor ClientSock.Create(FT:Boolean;{port,}IP:string;CN:integer); var s:byte; begin inherited Create(FT); N:=CN; client:=clients[N]; //定义协议族 ca.sin_family:=PF_INET; //tcp //将端口号由主机字节顺序转换为网络字节顺序;调用htons ca.sin_port:=htons(StrToint('1024')); //端口号 //调用inet_addr函数将点分制十进制IP地址转换成网络地址, //此过程隐含地实现了到网络字节的转换; Hostaddr:=inet_addr(PChar(trim(ip))); //ip地址 if hostaddr=-1 then begin F_main.Memo1.Lines.Add('主机IP地址'+ip+'错误'); F_main.client_close(N); //写日制文件 F_main.File_today('主机IP地址'+ip+'错误sock'+IntTostr(N)); closeSocket(Client); if (F_octem.T[N]=12) and (F_octem.ListBox1.Items.Count=0) then //判断是否还有IP地址未连接 begin F_octem.Memo1.Clear ; F_octem.Memo1.Lines.Add('巡检结束!') end; Exit; end else begin //转换成功对地址赋值 ca.sin_addr.S_addr:=hostaddr; //连接由协议族、地址、端口三元组确定了的服务器端; F_main.Edits[N].Text :='开始连接锁'+ip; F_main.Edits[N].Refresh ; if connect(Client,ca,sizeof(ca))<>0 then //连接失败 begin if F_octem.T[N]<>12 then begin F_octem.Memo1.Clear; F_octem.Memo1.Lines.Add('连接锁错误,锁IP:'+IP); end else begin F_Main.Memo1.Lines.Add('连接锁错误,锁IP:'+IP); if F_octem.ListBox1.Items.Count=0 then //判断是否还有IP地址未连接 begin F_octem.Memo1.Clear ; F_octem.Memo1.Lines.Add('巡检结束!') //F_octem.sock_xj; end; end; CloseSocket(Client); F_main.client_close(N); //写日制文件 F_main.File_today('连接锁错误,锁IP:'+IP+'sock'+IntTostr(N)); exit; end else begin s:=38; //& Send(Client,s,1,0); F_main.Edits[N].Text :=Lock_id[N]+'发送握手信号'; F_main.Edits[N].Refresh ; //写日制文件 F_main.File_today(Lock_id[N]+'发送握手信号sock'+IntTostr(N)); end; end; // FreeOnTerminate:=True; //终止线程 SusPended:=False; //启用线程 end; Function TF_Octem.sock_YN(Tt:integer;sock_ip:string;ofdids:string):String; // begin if onconnect[0]=0 then begin F_main.Edits[0].Text :='操作锁'+ofdids; F_main.Edits[0].Refresh ; //写日制文件 F_main.File_today('操作锁'+ofdids); Clients[0]:=Socket(PF_INET,SOCK_STREAM,IPPROTO_IP); if Clients[0]=INVALID_SOCKET then //创建错误 begin F_main.Memo1.Lines.Add('为连接锁创建Socket错误!'); if (Tt=12) and (F_octem.ListBox1.Items.Count>0) then //判断是否还有IP地址未连接 begin sock_xj; end; end else begin F_main.Edits[0].Text :='为锁'+ofdids+'创建socket'; F_main.Edits[0].Refresh ; //写日制文件 F_main.File_today('为锁'+ofdids+'创建socket'); T[0]:=Tt; lock_ip[0]:=Sock_ip; Lock_id[0]:=ofdids; onconnect[0]:=1; clientsock.Create(True,Sock_ip,0) ; end; result:='1'; end else if onconnect[1]=0 then begin F_main.Edits[1].Text :='操作锁'+ofdids; //写日制文件 F_main.File_today('操作锁'+ofdids); Clients[1]:=Socket(PF_INET,SOCK_STREAM,IPPROTO_IP); if Clients[1]=INVALID_SOCKET then //创建错误 begin F_main.Memo1.Lines.Add('为连接锁创建Socket错误!'); if (Tt=12) and (F_octem.ListBox1.Items.Count>0) then //判断是否还有IP地址未连接 begin sock_xj; end; end else begin F_main.Edits[1].Text :='为锁'+ofdids+'创建socket'; F_main.Edits[1].Refresh ; //写日制文件 F_main.File_today('为锁'+ofdids+'创建socket'); T[1]:=Tt; lock_ip[1]:=Sock_ip; Lock_id[1]:=ofdids; onconnect[1]:=1; clientsock.Create(True,Sock_ip,1) ; end; result:='2'; end else begin result:='0'; end; end;
不使用Synchronize方法,就可以了。
根据你的应用要求,应该是可以的。
FreeOnTerminate:=True;
Execute;FreeOnTerminate:=True;
这句话的意思是线程关闭后自动释放。
Execute;
这句不要了,因为在线程创建时会自动找这个Execute里方法进行执行。关于同步问题,主要是让线程执行完成后,通知主进程来执行OnTerminate
里定义的事件。关于边际问题,只要做好处理好公共变量的调用问题,一般就没有问题。你目前的问题是在同一程序中,起同一任务的线程。
而我们一般遇到的问题都是不同任务的线程。所以,你这儿的要求有点特殊。
不过好佝打开时有点小问题你用delphi那个版本??
我是用d5..
那我怎么可发做到同一任务的线程..
自己创立一个 Form 用来实现对 VCL 的线程级的安全调用。
可能问题就是出现在这里了,至于怎么解决,我也不太清楚
(我刚学delphi不久),你可以尝试在线程中释放时间段,也许会有用。
use API function: Sleep(...) or use delphi function ProcessMessage;
clientsock = class(TThread)
private
Client:Tsocket;
N:integer;
Procedure Timerun(N:integer);
{ Private declarations }
protected
procedure Execute; override;
Public
constructor Create(FT:Boolean;{port,}IP:string;CN:integer);
end;
Procedure Clientsock.Timerun(N:integer);
const
BlockLen=1024*4;
var
s: array[0..BlockLen-1] of byte;
z:byte;
st,st1,ls_ic:string;
r,i,j,K:integer;
evttime:Tdatetime;
begin
r:=recv(Client,s,BlockLen,0) ; //收到的字节数
if r=0 then exit ; if Ft[N]=0 then
begin
if s[0]=38 then //收到&
begin
F_main.Edits[N].Text :=Lock_id[N]+'巡检握手成功';
F_main.Edits[N].Refresh ;
//写日制文件
F_main.File_today('巡检握手成功Client'+IntTostr(N)); s_time[N]:=FormatDateTime('YYYYMMDDHHMM',now());
xor_time[N]:=F_main.Compute_xor(s_time[N]); //计算时间密钥
F_main.Sic_com('L06'+s_time[N]+xor_time[N],12,0);
Send(Client,F_main.Dsic[N],9,0); //发送巡检
F_main.Edits[N].Text :=Lock_id[N]+'巡检发送时间';
F_main.Edits[N].Refresh ;
Ft[N]:=Ft[N]+1;
end;
end
else
begin
if Ft[N]>3 then
begin
F_main.Memo1.Lines.Add(Lock_id[N]+'重发三次错误,锁可能故障,请检查锁状态1');
closeSocket(Client);
F_main.Client_Close(N);
//写日制文件
F_main.File_today(Lock_id[N]+'巡检失败Client'+IntTostr(N));
Terminate;
F_octem.sock_xj;//判断巡检结束没有
exit;
end
else
begin
//判断接收正确
j:=s[0];
for i:=1 to r-1 do
begin
j:=j xor s[i];
end;
if j<>0 then
begin
z:=37; //%
//写日制文件
F_main.File_today(Lock_id[N]+'巡检接收错误sock'+IntTostr(N));
Send(Client,z,1,0);
F_main.Edits[N].Text :=Lock_id[N]+'巡检重发';
F_main.Edits[N].Refresh ;
Ft[N]:=Ft[N]+1;
end
else
if j =0 then
begin
z:=36; //$
Send(Client,z,1,0);
//写日制文件
F_main.File_today(Lock_id[0]+'巡检接收正确');
F_main.Memo1.Lines.Add('锁巡检正确锁号:'+Lock_id[N]);
closeSocket(Client);
F_main.Client_Close(N);
//把Byte转成string
for i:=0 to (r-1) do
begin
if s[i]=10 then st:=st+'a'
else
if s[i]=11 then st:=st+'b'
else
if s[i]=12 then st:=st+'c'
else
if s[i]=13 then st:=st+'d'
else
if s[i]=14 then st:=st+'e'
else
if s[i]=15 then st:=st+'f'
else
st:=st+char(s[i]); //
end;
//写日制文件
F_main.File_today(Lock_id[N]+'巡检接收正确sock '+IntTostr(N)+st); for k:=1 to (r-4)div 20 do
begin
st1:=copy(st,3+(k-1)*20,20);
evttime:=StrToDatetime(copy(st1,1,4)+'-'+copy(st1,5,2)+'-'+copy(st1,7,2)+' '+copy(st1,9,2)+':'+copy(st1,11,2));
ls_ic:=copy(st1,13,8);
F_main.Insert_ofdevtlog(Lock_id[N],evttime,'0',ls_ic);
end;
Terminate;
//if F_octem.T[1]=0 then Terminate;
if not F_octem.Li then F_octem.sock_xj;//判断巡检结束没有
end;
end;
end;
end;
procedure clientsock.Execute;
begin
while not Terminated do
begin
Application.ProcessMessages ;
if F_octem.T[0]>0 then Timerun(0);;
if F_octem.T[1]>0 the Timerun(1);
end;
end;
constructor ClientSock.Create(FT:Boolean;{port,}IP:string;CN:integer);
var
s:byte;
begin
inherited Create(FT);
N:=CN;
client:=clients[N];
//定义协议族
ca.sin_family:=PF_INET; //tcp
//将端口号由主机字节顺序转换为网络字节顺序;调用htons
ca.sin_port:=htons(StrToint('1024')); //端口号
//调用inet_addr函数将点分制十进制IP地址转换成网络地址,
//此过程隐含地实现了到网络字节的转换;
Hostaddr:=inet_addr(PChar(trim(ip))); //ip地址
if hostaddr=-1 then
begin
F_main.Memo1.Lines.Add('主机IP地址'+ip+'错误');
F_main.client_close(N);
//写日制文件
F_main.File_today('主机IP地址'+ip+'错误sock'+IntTostr(N));
closeSocket(Client);
if (F_octem.T[N]=12) and (F_octem.ListBox1.Items.Count=0) then //判断是否还有IP地址未连接
begin
F_octem.Memo1.Clear ;
F_octem.Memo1.Lines.Add('巡检结束!')
end;
Exit;
end
else
begin
//转换成功对地址赋值
ca.sin_addr.S_addr:=hostaddr;
//连接由协议族、地址、端口三元组确定了的服务器端;
F_main.Edits[N].Text :='开始连接锁'+ip;
F_main.Edits[N].Refresh ; if connect(Client,ca,sizeof(ca))<>0 then //连接失败
begin
if F_octem.T[N]<>12 then
begin
F_octem.Memo1.Clear;
F_octem.Memo1.Lines.Add('连接锁错误,锁IP:'+IP);
end
else
begin
F_Main.Memo1.Lines.Add('连接锁错误,锁IP:'+IP);
if F_octem.ListBox1.Items.Count=0 then //判断是否还有IP地址未连接
begin
F_octem.Memo1.Clear ;
F_octem.Memo1.Lines.Add('巡检结束!')
//F_octem.sock_xj;
end;
end;
CloseSocket(Client);
F_main.client_close(N);
//写日制文件
F_main.File_today('连接锁错误,锁IP:'+IP+'sock'+IntTostr(N));
exit;
end
else
begin
s:=38; //&
Send(Client,s,1,0);
F_main.Edits[N].Text :=Lock_id[N]+'发送握手信号';
F_main.Edits[N].Refresh ;
//写日制文件
F_main.File_today(Lock_id[N]+'发送握手信号sock'+IntTostr(N));
end;
end;
// FreeOnTerminate:=True; //终止线程
SusPended:=False; //启用线程
end;
Function TF_Octem.sock_YN(Tt:integer;sock_ip:string;ofdids:string):String; //
begin
if onconnect[0]=0 then
begin
F_main.Edits[0].Text :='操作锁'+ofdids;
F_main.Edits[0].Refresh ;
//写日制文件
F_main.File_today('操作锁'+ofdids); Clients[0]:=Socket(PF_INET,SOCK_STREAM,IPPROTO_IP); if Clients[0]=INVALID_SOCKET then //创建错误
begin
F_main.Memo1.Lines.Add('为连接锁创建Socket错误!');
if (Tt=12) and (F_octem.ListBox1.Items.Count>0) then //判断是否还有IP地址未连接
begin
sock_xj;
end;
end
else
begin
F_main.Edits[0].Text :='为锁'+ofdids+'创建socket';
F_main.Edits[0].Refresh ;
//写日制文件
F_main.File_today('为锁'+ofdids+'创建socket');
T[0]:=Tt;
lock_ip[0]:=Sock_ip;
Lock_id[0]:=ofdids;
onconnect[0]:=1;
clientsock.Create(True,Sock_ip,0) ;
end;
result:='1';
end
else
if onconnect[1]=0 then
begin
F_main.Edits[1].Text :='操作锁'+ofdids;
//写日制文件
F_main.File_today('操作锁'+ofdids);
Clients[1]:=Socket(PF_INET,SOCK_STREAM,IPPROTO_IP);
if Clients[1]=INVALID_SOCKET then //创建错误
begin
F_main.Memo1.Lines.Add('为连接锁创建Socket错误!');
if (Tt=12) and (F_octem.ListBox1.Items.Count>0) then //判断是否还有IP地址未连接
begin
sock_xj;
end;
end
else
begin
F_main.Edits[1].Text :='为锁'+ofdids+'创建socket';
F_main.Edits[1].Refresh ;
//写日制文件
F_main.File_today('为锁'+ofdids+'创建socket');
T[1]:=Tt;
lock_ip[1]:=Sock_ip;
Lock_id[1]:=ofdids;
onconnect[1]:=1;
clientsock.Create(True,Sock_ip,1) ;
end;
result:='2';
end
else
begin
result:='0';
end;
end;