当 OnConnect 事件与 Lazarus 中另一个表单的 TTabControls 选项卡交互时,Indy10 上的服务器进程 运行 部分停止响应
Server process running on Indy10 partially stops responding when OnConnect event interacts with a TTabControls Tabs from another form in Lazarus
试图在标题中描述我的大部分问题,我基本上做到了。
基本上,我在 Lazarus 中使用 Indy 10 制作了自己的小型 TCP 服务器。它所做的只是接受字节形式的数据包,这些数据包包含代表英文字母的某个 char
。我正在用 Context
s' IOHandler
读取这些字节,如下所示:
procedure TServerSideForm.OnExecuteServer(Context: TIdContext);
var
IO: TIdIOHandler;
keyPressed: char;
begin
//
IO := Context.Connection.IOHandler;
if not(IO.InputBufferIsEmpty) then
begin
LogForm.LogToForm('Recieving a packet from ' + Context.Binding.IP + '(' + Context.Binding.PeerIP + ')');
keyPressed := IO.ReadChar;
AddKeyToAppropriateClient(keyPressed, Context.Binding.IP);
end;
IndySleep(10);
//
end;
这很完美。
但是,我有另一个表格,里面有一个 TTabControl
,每个连接到我的服务器的用户都有一个选项卡,每个选项卡中还有一个 TMemo
。选项卡和备忘录是在 运行 时创建的,执行此操作的函数不会抛出任何异常。
我的其他表单中的 AddTab()
函数如下所示(用于创建上述选项卡和备忘录):
procedure TConnectionsForm.AddTab(IP: string);
var
newMemo: TMemo;
begin
ConnectionTabs.Tabs.Add(IP);
currTabIndx := ConnectionTabs.TabIndex;
newMemo := TMemo.Create(ConnectionsForm);
newMemo.AnchorSide[akTop].Side:=asrTop;
newMemo.AnchorSide[akTop].Control:=ConnectionTabs;
newMemo.BorderSpacing.Top:=2;
newMemo.AnchorSide[akBottom].Side:=asrBottom;
newMemo.AnchorSide[akBottom].Control:=ConnectionTabs;
newMemo.BorderSpacing.Bottom:=2;
newMemo.AnchorSide[akLeft].Side:=asrLeft;
newMemo.AnchorSide[akLeft].Control:=ConnectionTabs;
newMemo.BorderSpacing.Left:=2;
newMemo.AnchorSide[akRight].Side:=asrRight;
newMemo.AnchorSide[akRight].Control:=ConnectionTabs;
newMemo.BorderSpacing.Right:=2;
newMemo.Anchors := [akTop, akBottom, akLeft, akRight];
newMemo.Parent := ConnectionTabs;
newMemo.Visible:=true;
newMemo.Lines.Add(IP);
SetLength(connectionMessagesArr, Length(connectionMessagesArr)+1);
connectionMessagesArr[Length(connectionMessagesArr)-1] := newMemo;
ShowOnly(currTabIndx);
end;
看起来还不错,我已经自己测试了很多次了。
但是当我 运行 从我的 OnConnect
函数中为我的 TIdTCPServer
执行该功能时,服务器进程似乎冻结,直到发生其他事件,例如 OnExecute
, 发生。当 OnExecute
确实执行时,进程已接受的消息也将执行。例如,如果我的程序冻结,当它冻结时,我将尝试最小化我的一个表单并将一些其他表单移动到屏幕上的其他地方,他们将在程序解冻后执行此操作。
这是我自己的 OnConnect
函数:
procedure TServerSideForm.OnConnectServer(Context: TIdContext);
begin
LogForm.LogToForm(Context.Binding.IP + ' has connected to the server (' + Context.Binding.PeerIP + ')');
//ConnectionsForm.AddTab(Context.Binding.PeerIP); // Boom
//ConnectionsForm.ConnectionTabs.Tabs.Add('!!'); // Boom
end;
正如我在标题中所述,与 TTabControl
选项卡的任何类型的交互都会使程序冻结。 ConnectionsForm.ConnectionTabs.Tabs.Add('!!');
也会使程序冻结(这里,ConnectionsTabs
是我的 TTabControl
表单中的变量,名为 ConnectionsForm
)。
我真的不知道这里发生了什么,所以非常感谢您的帮助。
嗯,是的,我的程序确实是线程不安全的。
通过添加我的小同步解决了问题 class:
type
TMySync = class(TIdSync)
protected
procedure DoSynchronize; override;
public
context: TIdContext;
end;
并在其 DoSyncronize
重写函数中执行我所有的 TTabControl
恶作剧。
procedure TMySync.DoSynchronize;
begin
LogForm.LogToForm(Context.Binding.IP + ' has connected to the server (' + Context.Binding.PeerIP + ')');
ConnectionsForm.AddTab(Context.Binding.PeerIP);
end;
并且OnConnect
已更改为:
procedure TServerSideForm.OnConnectServer(Context: TIdContext);
var
sync: TMySync;
begin
//
sync := TMySync.Create;
try
sync.context := Context;
sync.Synchronize;
finally
Sync.Free;
end;
end;
P.S。
对我的 OnDisconnect
函数做了类似的操作。
目前看来一切正常。
试图在标题中描述我的大部分问题,我基本上做到了。
基本上,我在 Lazarus 中使用 Indy 10 制作了自己的小型 TCP 服务器。它所做的只是接受字节形式的数据包,这些数据包包含代表英文字母的某个 char
。我正在用 Context
s' IOHandler
读取这些字节,如下所示:
procedure TServerSideForm.OnExecuteServer(Context: TIdContext);
var
IO: TIdIOHandler;
keyPressed: char;
begin
//
IO := Context.Connection.IOHandler;
if not(IO.InputBufferIsEmpty) then
begin
LogForm.LogToForm('Recieving a packet from ' + Context.Binding.IP + '(' + Context.Binding.PeerIP + ')');
keyPressed := IO.ReadChar;
AddKeyToAppropriateClient(keyPressed, Context.Binding.IP);
end;
IndySleep(10);
//
end;
这很完美。
但是,我有另一个表格,里面有一个 TTabControl
,每个连接到我的服务器的用户都有一个选项卡,每个选项卡中还有一个 TMemo
。选项卡和备忘录是在 运行 时创建的,执行此操作的函数不会抛出任何异常。
我的其他表单中的 AddTab()
函数如下所示(用于创建上述选项卡和备忘录):
procedure TConnectionsForm.AddTab(IP: string);
var
newMemo: TMemo;
begin
ConnectionTabs.Tabs.Add(IP);
currTabIndx := ConnectionTabs.TabIndex;
newMemo := TMemo.Create(ConnectionsForm);
newMemo.AnchorSide[akTop].Side:=asrTop;
newMemo.AnchorSide[akTop].Control:=ConnectionTabs;
newMemo.BorderSpacing.Top:=2;
newMemo.AnchorSide[akBottom].Side:=asrBottom;
newMemo.AnchorSide[akBottom].Control:=ConnectionTabs;
newMemo.BorderSpacing.Bottom:=2;
newMemo.AnchorSide[akLeft].Side:=asrLeft;
newMemo.AnchorSide[akLeft].Control:=ConnectionTabs;
newMemo.BorderSpacing.Left:=2;
newMemo.AnchorSide[akRight].Side:=asrRight;
newMemo.AnchorSide[akRight].Control:=ConnectionTabs;
newMemo.BorderSpacing.Right:=2;
newMemo.Anchors := [akTop, akBottom, akLeft, akRight];
newMemo.Parent := ConnectionTabs;
newMemo.Visible:=true;
newMemo.Lines.Add(IP);
SetLength(connectionMessagesArr, Length(connectionMessagesArr)+1);
connectionMessagesArr[Length(connectionMessagesArr)-1] := newMemo;
ShowOnly(currTabIndx);
end;
看起来还不错,我已经自己测试了很多次了。
但是当我 运行 从我的 OnConnect
函数中为我的 TIdTCPServer
执行该功能时,服务器进程似乎冻结,直到发生其他事件,例如 OnExecute
, 发生。当 OnExecute
确实执行时,进程已接受的消息也将执行。例如,如果我的程序冻结,当它冻结时,我将尝试最小化我的一个表单并将一些其他表单移动到屏幕上的其他地方,他们将在程序解冻后执行此操作。
这是我自己的 OnConnect
函数:
procedure TServerSideForm.OnConnectServer(Context: TIdContext);
begin
LogForm.LogToForm(Context.Binding.IP + ' has connected to the server (' + Context.Binding.PeerIP + ')');
//ConnectionsForm.AddTab(Context.Binding.PeerIP); // Boom
//ConnectionsForm.ConnectionTabs.Tabs.Add('!!'); // Boom
end;
正如我在标题中所述,与 TTabControl
选项卡的任何类型的交互都会使程序冻结。 ConnectionsForm.ConnectionTabs.Tabs.Add('!!');
也会使程序冻结(这里,ConnectionsTabs
是我的 TTabControl
表单中的变量,名为 ConnectionsForm
)。
我真的不知道这里发生了什么,所以非常感谢您的帮助。
嗯,是的,我的程序确实是线程不安全的。
通过添加我的小同步解决了问题 class:
type
TMySync = class(TIdSync)
protected
procedure DoSynchronize; override;
public
context: TIdContext;
end;
并在其 DoSyncronize
重写函数中执行我所有的 TTabControl
恶作剧。
procedure TMySync.DoSynchronize;
begin
LogForm.LogToForm(Context.Binding.IP + ' has connected to the server (' + Context.Binding.PeerIP + ')');
ConnectionsForm.AddTab(Context.Binding.PeerIP);
end;
并且OnConnect
已更改为:
procedure TServerSideForm.OnConnectServer(Context: TIdContext);
var
sync: TMySync;
begin
//
sync := TMySync.Create;
try
sync.context := Context;
sync.Synchronize;
finally
Sync.Free;
end;
end;
P.S。
对我的 OnDisconnect
函数做了类似的操作。
目前看来一切正常。