WindowFreeze VCL

Ben*_*iss 0 delphi multithreading vcl indy delphi-7

我有一个Delphi7项目,大约有10个窗口.程序启动时会加载MainWindow.过了一会儿,MainWindow访问项目的另一个窗口,添加listview项目,并在1-2秒内更新它们.然而,在我打开它之后,这个窗口似乎冻结了并且根本没有显示列表视图.

如果我在MainWindow的OnShow过程中有以下命令,它可以工作:

SecondWindow.Show;
SecondWindow.Close;
Run Code Online (Sandbox Code Playgroud)

它没有问题,但似乎不专业.任何想法如何绘制窗口而不显示?

编辑:代码(我使用Indy9)

procedure TMainWindow.ServerSocketExecute(AThread: TIdPeerThread);
begin
 /....
 if Buffer = 'additem' then begin
    Window2.ListView1.Items.Add;
    Exit;
    // .....
 end;
end;
Run Code Online (Sandbox Code Playgroud)

而已.我删除了Window2上的所有计时器,似乎仍然要冻结.如果添加了一个项目或者我第一次尝试打开第二个Windows时,mainWindow会立即冻结.

Dav*_*nan 6

您的问题是您从主GUI线程外部调用VCL方法,即在TMainWindow.ServerSocketExecute中.此事件在工作线程中执行.从工作线程调用VCL/GUI代码完全违反了游戏规则.所有VCL代码必须在主GUI线程中执行.

因此,通过确保所有VCL/GUI代码在GUI线程中执行来解决问题.使用TIdPeerThread.Synchronize()方法或TIdSync或TIdNotify类来实现此目的.

感谢@Remy提供我不知道的细节.

  • 详细说明,`TIdTCPServer`是一个多线程组件.`onExecute`事件在工作线程的上下文中触发,该工作线程由提供的`TIdPeerThread`对象管理,而不是在主UI线程的上下文中.VCL UI操作,例如将项添加到`TListView`,只能在主UI线程的上下文中工作.要在`OnExecute`事件中执行UI操作,必须使用`TIdPeerThread.Synchronize()`方法或`TIdSync`或`TIdNotify`类与主线程同步. (4认同)