我正在使用带有IdTCPServer的表单来管理来自客户端的字符串,其中包含AThread.connection.readln / writeln系统。字符串处理有效,这不是问题。
问题是,服务器上的表单挂起并且不会加载,但它仍然管理连接到它的所有客户端,因此它正在运行,但它不能用作表单。 我会猜测它是坐在阅读线上还是什么东西......但是我不知道如何在这个时刻解决这个问题。
请帮忙。
procedure TMonitorFrm.ServerExecute(AThread: TIdPeerThread);
procedure post(PostMessage:string);
begin
try
AThread.Connection.WriteLn(PostMessage);
except
showmessage('Cannot post');
end;
end;
var
ActClient : PClient;
sTemp,
CommBlock,
NewCommBlock,
ReceiverName,
sContent,
sSQL,
sCommand : String;
iCount2,
iCount : Integer;
sldb : TSQLiteDatabase;
sltb : TSQLiteTable;
begin
if not AThread.Terminated and AThread.Connection.Connected then
begin
CommBlock := AThread.Connection.ReadLn();
ActClient := PClient(AThread.Data);
ActClient.LastAction := Now;
sCommand := copy(CommBlock,0,pos(',',CommBlock)-1); {seperate command}
sContent := copy(CommBlock,pos(',',CommBlock)+1,length(CommBlock)-(pos(',',CommBlock)+1)); {seperate data block}
iCount:= 0 ;
if sCommand = 'Announce' then //SPECIAL
begin
{ Do stuff for this command...}
end
else if sCommand = 'CheckSect' then
{Etcetera...}
procedure TMonitorFrm.FormCreate(Sender: TObject);
var
sCompetitionID : string;
sldb : TSQLiteDatabase;
sltb : TSQLiteTable;
begin
Clients := TThreadList.Create;
Server.Active := True;
AreaPnlList := TComponentList.Create;
SectionPnlList := TComponentList.Create;
Repeat until InputQuery('Competition Select', 'Please type the ID of the competition', sCompetitionID);
iCompetitionID:=StrToInt(sCompetitionID);
OpenDatabase(slDb);
sltb:=slDb.GetTable('SELECT * FROM SectionTable WHERE CompetitionID='+sCompetitionID);
Frame31.CreateSections(sltb,Frame31);
sltb.Free;
CloseDatabase(slDb);
{
This section needs to check the SQLite databases for sections and list them in the display window and makes a drag n drop profile...
}
end;
答案 0 :(得分:6)
Indy使用阻塞套接字。 假定挂起当前线程。要在VCL线程中使用Indy组件同时保持VCL线程响应,请在表单上放置TIdAntifreeze
组件。 Indy组件知道该组件并定期对其进行控制,以便您的VCL线程可以继续处理消息。
答案 1 :(得分:4)
如果您认为无法使用调试器可靠地跟踪执行情况,则可以在代码中添加一些显式跟踪信息。
使用OutputDebugString
在从IDE运行时在IDE EventLog中记录信息,或者在Delphi外部运行时记录 DbgView窗口(来自SysInternals)。
答案 2 :(得分:0)
请记住,VCL组件不是线程安全的,因此您无法直接从线程访问它们,否则会出现问题,例如主线程可能会卡住。
因此,请检查TMonitorFrm.ServerExecute是否对表单和组件不执行任何操作。如果您需要更新某些内容,请使用Synchronize。
答案 3 :(得分:0)
这是停止Readln导致它冻结的方法。你需要检查是否有东西可以先阅读。有几种方法可以做到这一点,你可以进行readln超时
Repeat
CommBlock := '';
CommBlock := AThread.Connection.ReadLn('',10);
Application.ProcessMessages;
until Commblock <> '';
或者您可以在尝试阅读之前检查连接是否可读。
Repeat
CommBlock:='';
if AThread.Connection.IOHandler.Readable()then
begin
CommBlock := AThread.Connection.ReadLn();
end
else
begin
application.ProcessMessages;
end;
until commblock <> '';
无论哪种方式,关键行都是Application.ProcessMessages,因为这允许主线程检查其消息并继续运行。