怎么解决在自定义类中使用TThread所产生的异常(100分)

  • 主题发起人 kevinywb
  • 开始时间
K

kevinywb

Unregistered / Unconfirmed
GUEST, unregistred user!
如题,研究了好久都解决不了,求各位高手帮帮忙
我的代码如下:
unit TCPNetComm1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, IdTCPClient, IdTCPServer, StdCtrls
;
type
TDataInfo = record // 数据信息
Command, // 命令
MyUserName, // 发送者
Data, // 所要发送的数据
ReceiverName: string[100];
// 接收者
end;

PClient = ^TClient;
TClient = record // 客户端信息
DNS : String[20];
//主机名
Connected, //连接时间
LastAction : TDateTime;
//最后一次操作时间
Thread : Pointer;
//线程指针
end;

TClientHandleThread = class(TThread)//自定义线程
private
Data : TDataInfo;
procedure HandleInput;
protected
procedure Execute;
override;
end;

TClientMan = class(TObject)
private
FClient : TIdTCPClient;
FMemo : TMemo;
ClientHandleThread : TClientHandleThread;
public
constructor create(aClient:TIdTCPClient;AMemo:TMemo);
destructor destroy;
override;
procedure connect(aip:string;aport:integer);//建立连接
procedure disconn();//断开连接
procedure sendData2Sevr(Command,SendData,RecvName:string);//向服务器发送数据
procedure sendHS2Sevr();//向服务器发送心跳信号
end;

TSevrMan = class(TObject)
private
FIP : string;
FPort : integer;
FSevr : TIdTCPServer;
FMemo : TMemo;
FSevrlist : TThreadList;
//客户端列表
RecThread : TIdPeerThread;//客户端线程
public
constructor create(aSevr:TIdTCPServer;AMemo:TMemo);
destructor destroy;
override;
procedure startSevr();
procedure stopSevr();
procedure connect(AThread: TIdPeerThread);
procedure disconn(AThread: TIdPeerThread);
procedure execute(AThread: TIdPeerThread);
procedure sendData2Client(Command,SendData,RecvName:string);
property IP : string read FIP write FIP;
property Port : integer read FPort write FPort;
end;

implementation
//------------------------------------------------------------------------------
// TClientHandleThread = class(TThread)//自定义线程
// DataInfo : TDataInfo;
//------------------------------------------------------------------------------
//private
procedure TClientHandleThread.HandleInput;
var
Client : TClientMan;
begin
if Data.Command = 'MESSAGE' then
Client.FMemo.Lines.Add(Data.MyUserName + ': ' + Data.Data)
else
MessageDlg('无效命令 '+Data.Command+' containing this message:'+#13+Data.Data, mtError, [mbOk], 0);
end;

//protected
procedure TClientHandleThread.Execute;
var
Client : TClientMan;
begin
while not Terminateddo
begin
if not Client.FClient.Connected then
Terminate
else
try
Client.FClient.ReadBuffer(Data, SizeOf (Data));
Synchronize(HandleInput);
except
end;
end;
inherited;
end;

//------------------------------------------------------------------------------
// TClientMan = class(TObject)
// FIP : string;
// FPort : integer;
// FSevr : TIdTCPServer;
// FClient : TIdTCPClient;
// FMemo : TMemo;
// FSevrlist : TThreadList;
//
// property IP : string read FIP write FIP;
// property Port : integer read FPort write FPort;
//------------------------------------------------------------------------------
//private
//public
constructor TClientMan.create(aClient:TIdTCPClient;AMemo:TMemo);
begin
if assigned(FClient) then
exit;
if assigned(FMemo) then
exit;
FClient := aClient;
FMemo := AMemo;
end;

destructor TClientMan.destroy;
begin
FClient.Disconnect;
inherited;
end;

procedure TClientMan.connect(aip:string;aport:integer);//建立连接
begin
FClient.Host := aip;
FClient.Port := aport;
try
FMemo.Lines.Add('正在连接服务器'+aip+'...');
FClient.Connect(5000);
if FClient.Connected then
FMemo.Lines.Add('同服务器'+aip+'已经建立连接');

//对TThread进行创建
ClientHandleThread := TClientHandleThread.Create(True);
ClientHandleThread.FreeOnTerminate := True;
ClientHandleThread.Resume;
except
FMemo.Lines.Add('同服务器'+aip+'连接失败');
end;
end;

procedure TClientMan.disconn();//断开连接
begin
FMemo.Lines.Add('同服务器的连接已经断开');
FClient.Disconnect;
end;

procedure TClientMan.sendData2Sevr(Command,SendData,RecvName:string);//向服务器发送数据
var
Data : TDataInfo;
begin
Data.Command := Command;
Data.MyUserName := FClient.LocalName;
Data.Data := SendData;
Data.ReceiverName := RecvName;
FClient.WriteBuffer(Data, SizeOf (Data), true);
end;

procedure TClientMan.sendHS2Sevr();//向服务器发送心跳信号
var
Data : TDataInfo;
begin
Data.Command := 'Listening';
Data.MyUserName := FClient.LocalName;
Data.Data := '';
Data.ReceiverName := 'server';
FClient.WriteBuffer(Data,sizeof(Data),true);
end;

//------------------------------------------------------------------------------
// TSevrMan = class(TObject)
// FIP : string;
// FPort : integer;
// FSevr : TIdTCPServer;
// FClient : TIdTCPClient;
// FMemo : TMemo;
// FSevrlist : TThreadList;
//客户端列表
// RecThread : TIdPeerThread;//客户端线程
//------------------------------------------------------------------------------
//private
//public
constructor TSevrMan.create(aSevr:TIdTCPServer;AMemo:TMemo);
begin
if assigned(FSevr) then
exit;
if assigned(FMemo) then
exit;
FIP := '127.0.0.1';
FPort := 3333;
FSevr := aSevr;
FMemo := AMemo;
FSevr.Active := false;
FSevrlist := TThreadList.Create;
end;

destructor TSevrMan.destroy;
begin
FSevr.Active := false;
FSevrlist.Free;
end;

procedure TSevrMan.startSevr();
begin
FSevr.Active := true;
FSevr.DefaultPort := FPort;
end;

procedure TSevrMan.stopSevr();
begin
FSevr.Active := false;
end;

procedure TSevrMan.connect(AThread: TIdPeerThread);
var
NewClient: PClient;
begin
GetMem(NewClient, SizeOf(TClient));
NewClient.DNS := AThread.Connection.Socket.Binding.PeerIP;
NewClient.Connected := Now;
NewClient.LastAction := NewClient.Connected;
NewClient.Thread := AThread;
AThread.Data := TObject(NewClient);
try
FSevrlist.LockList.Add(NewClient);
finally
FSevrlist.UnlockList;
end;
FMemo.Lines.Add(TimeToStr(Time)+' 已连接 "'+NewClient.DNS+'"');
end;

procedure TSevrMan.disconn(AThread: TIdPeerThread);
var
ActClient: PClient;
begin
ActClient := PClient(AThread.Data);
FMemo.Lines.Add (TimeToStr(Time)+' 断开连接 "'+ActClient^.DNS+'"');
try
FSevrlist.LockList.Remove(ActClient);
finally
FSevrlist.UnlockList;
end;
FreeMem(ActClient);
AThread.Data := nil;
end;

procedure TSevrMan.execute(AThread: TIdPeerThread);
var
ActClient, RecClient : PClient;
Data, NewData : TDataInfo;
i : Integer;
begin
if not AThread.Terminated and AThread.Connection.Connected then
begin
AThread.Connection.ReadBuffer (Data, SizeOf(Data));
ActClient := PClient(AThread.Data);
ActClient.LastAction := Now;
// 更新最后操作时间
if Data.Command = 'MESSAGE' then
begin
//检测是否接收数据
if Data.ReceiverName = '' then
begin
FMemo.Lines.Add (TimeToStr(Time)+'['+AThread.Connection.Socket.Binding.PeerIP+
'] : "'+Data.Data+'"');
NewData := Data;
//数据没有改变
with FSevrlist.LockListdo
try
for i := 0 to Count-1do
begin
//遍历客户端
RecClient := Items;
//获取客户端
RecThread := RecClient.Thread;
//获取客户端线程
RecThread.Connection.WriteBuffer(NewData, SizeOf(NewData), True);//发送数据
end;
finally
FSevrlist.UnlockList;
end;
end
else
begin
//搜索客户端并发送数据
NewData := Data;
//数据没有改变
FMemo.Lines.Add(TimeToStr(Time)+'['+AThread.Connection.Socket.Binding.PeerIP+
'] to "'+Data.ReceiverName+'": "'+Data.Data+'"');
with FSevrlist.LockListdo
try
for i := 0 to Count-1do
begin
RecClient := Items;
if RecClient.DNS = Data.ReceiverName then
begin
//没有登录的功能,所以使用DNS(主机名)
RecThread := RecClient.Thread;
RecThread.Connection.WriteBuffer(NewData, SizeOf(NewData), True);
end;
end;
finally
FSevrlist.UnlockList;
end;
end;
end
else
begin
//无效命令
if Data.Command = 'Listening' then
begin
NewData := Data;
AThread.Connection.WriteBuffer(NewData, SizeOf(NewData), True);//发送数据
end
else
FMemo.Lines.Add (TimeToStr(Time)+' 无效命令来自 "'+Data.MyUserName+'": '+Data.Command);
//AThread.Connection.WriteBuffer (NewData, SizeOf (NewData), true);
end;
end;
end;

procedure TSevrMan.sendData2Client(Command,SendData,RecvName:string);
var
Data : TDataInfo;
RecClient : PClient;
i : integer;
begin
Data.Command := Command;
Data.MyUserName := FSevr.LocalName;
Data.Data := SendData;
Data.ReceiverName := RecvName;
if Data.ReceiverName = '' then
begin
FMemo.Lines.Add (TimeToStr(Time)+'['+Data.MyUserName+'] : "'+Data.Data+'"');
with FSevrlist.LockListdo
try
for i := 0 to Count-1do
begin
//遍历客户端
RecClient := Items;
//获取客户端
RecThread := RecClient.Thread;
//获取客户端线程
RecThread.Connection.WriteBuffer(Data,sizeof(data),true);//发送数据
end;
finally
FSevrlist.UnlockList;
end;
end
else
begin
FMemo.Lines.Add(TimeToStr(Time)+'['+Data.MyUserName+
'] to "'+Data.ReceiverName+'": "'+Data.Data+'"');
with FSevrlist.LockListdo
try
for i := 0 to Count-1do
begin
RecClient := Items;
if RecClient.DNS = Data.ReceiverName then
begin
//没有登录的功能,所以使用DNS(主机名)
RecThread := RecClient.Thread;
RecThread.Connection.WriteBuffer(Data, SizeOf(Data), True);
end;
end;
finally
FSevrlist.UnlockList;
end;
end;
end;
end.
顺便帮我看看这个类设计和代码的编写有什么问题
十分感谢
 
顶部