【问题标题】:Using TServerSocket (Non-Block I/O) inside a child thread (TThread)在子线程 (TThread) 中使用 TServerSocket(非块 I/O)
【发布时间】:2016-04-12 19:37:21
【问题描述】:

我正在从TThread 继承的类中创建TServerSocket 的实例。我的问题是,Execute 过程中应该包含什么代码,它是主线程代​​码?

TServerThread = class(TThread)
private
  FServerSocket: TServerSocket;

  // FServerSocket event handlers
  procedure ClientConnect(Sender: TObject; Socket: TCustomWinSocket);
  procedure ClientDisconnect(Sender: TObject; Socket: TCustomWinSocket);
  procedure ClientError(Sender: TObject; Socket: TCustomWinSocket; ErrorEvent: TErrorEvent; var ErrorCode: Integer);
  procedure ClientRead(Sender: TObject; Socket: TCustomWinSocket);
  procedure Listen(Sender: TObject; Socket: TCustomWinSocket);
protected
  procedure Execute; override;
public
  constructor Create;
  destructor Destroy; override;
end;

这就是类的外观,因此您将了解其实现的外观。

我问这个的原因是因为所有主要代码都发生在事件处理程序中,我想不出 MAIN 过程(执行)应该做的任何繁忙的工作操作,除了循环和睡眠?

here 中,有人建议使用消息循环,但我认为该线程不会接收任何消息。

【问题讨论】:

    标签: delphi sockets


    【解决方案1】:

    TServerSocket在非阻塞模式下使用隐藏窗口来处理socket活动的窗口消息,因此线程的Execute()方法需要有一个活动的消息循环来分发这些消息,例如:

    procedure TMyThread.Execute;
    var
      Msg: TMsg;
    begin
      ...
      ServerSocket.Active := True;
      try
        while not Terminated do
        begin
          if GetMessage(Msg, 0, 0, 0) > 0 then
          begin
            TranslateMessage(Msg);
            DispatchMessage(Msg);
          end else begin
            Break;
          end;
          ...
        end;
      finally
        ServerSocket.Active := False;
      end;
      ...
    end;
    
    procedure TMyThread.Stop;
    begin
      PostThreadMessage(ThreadID, WM_QUIT, 0, 0);
    end;
    

    【讨论】:

    • Q1Embarcadero 是否有关于隐藏窗口的文档,可以更好地向我解释Q2如果我理解正确,我不需要从构造函数中显式启动 TServerSocket,它将在 Execute 过程中启动Q3假设我将 TServerSocket 拖放到主窗体,并将其分配给构造函数内的子线程,主线程(Vlc 线程)是否处理​​那些隐藏的窗口消息 ?
    • Q1:不行。Q2:你必须激活Execute()里面的服务器。如果您在构造函数中激活它,隐藏窗口将与创建您的工作线程(可能是主线程)的线程上下文相关联,因此Execute() 将不会收到任何套接字的窗口消息。 Q3: 激活服务器的线程上下文将是接收套接字消息的线程上下文。
    • 出于好奇……你是怎么知道这个隐藏窗口的?
    • 隐藏窗口由AllocateHWnd()TCustomWinSocket.GetHandle()内部创建。 TCustomWinSocket.Handle 属性由TCustomWinSocket.AsyncInitSocket()TCustomWinSocket.DoSetAsyncStyles()TCustomWinSocket.DeferFree() 用于非阻塞套接字。 TCustomWinSocket.DoSetAsyncStyles()调用Winsock WSAAsyncSelect()函数注册窗口接收socket事件。
    • @user1803300:请研究一下 ScktComp.pas,所有的答案都在里面。你不需要自己直接处理窗口消息,你只需要为你的线程提供一个消息循环,这样消息就可以发送到TServerSocket,但前提是你以非阻塞模式开始使用它.
    猜你喜欢
    • 2022-08-16
    • 1970-01-01
    • 2013-05-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-21
    • 2011-04-05
    • 1970-01-01
    相关资源
    最近更新 更多