问题: 我在寻找什么是的 最典型的或最佳做法 的方式来使用一个单独的螺纹接收数据的使用IdTCPClient在Indy10.

背景: 以下代码是一样的我想要做到与实际数据处理部分除对的清晰度。这个想法的线,是接收所有数据(变量的大头宣布的其他信息的长度),并随后能够分析(这是什么HandleData程序)和触发事件处理根据该命令。

该TIdIOHandlerSocket传递给线的主要应用程序,它也将数据写入座,作为及时,这是必需的。

TScktReceiveThread = class(TThread)
  private
    { Private declarations }
    procedure HandleData;
  protected
    procedure Execute; override;
  public
    FSocket: TIdIOHandlerSocket;
    constructor Create(CreateSuspended: boolean);
  end;


procedure TScktReceiveThread.Execute;
var
  FixedHeader: TBytes;
begin
  Assert(FSocket <> nil, 'You must assign the connected socket to the receiving thread');
  SetLength(FixedHeader, 2);
   while not Terminated do
    begin
      if not FSocket.Connected then
        Suspend
      else
        begin
          FSocket.CheckForDataOnSource(10);
          if not FSocket.InputBufferIsEmpty then
           begin
            FSocket.ReadBytes(FixedHeader, SizeOf(FixedHeader), false);
            // Removed the rest of the reading and parsing code for clarity
            Synchronize(HandleData);
           end;
        end;
    end;
end;

作为前缀的,我们用另一个计算器问题涉及服务器部件的印:"德尔菲2009年,印第10日TIdTCPServer.OnExecute,如何抓住所有的字节的InputBuffer"获得基础什么我有这么远。

感谢任何的帮助!

有帮助吗?

解决方案

如果你想避免通过为每个线程类和每一个客户端 - 服务器的数据交换带来的开销,你可以在

描述的创建一个线程能动类

HTTP://delphidicas.blogspot。 COM / 2008/08 /匿名的方法-时-应该-它们-be.html

我前几天有同样的问题,我只是给我写一个类TMotileThreading它有让我使用D2009的新的匿名方法的功能创建线程静态函数。看起来是这样的:

type
  TExecuteFunc = reference to procedure;

  TMotileThreading = class
  public
    class procedure Execute (Func : TExecuteFunc);
    class procedure ExecuteThenCall (Func : TExecuteFunc; ThenFunc : TExecuteFunc);
  end;

第二个过程让我在你的情况下执行客户端 - 服务器通信等,并做一些东西只要数据已经到达。关于匿名方法的好处是,你可以使用调用上下文的局部变量。因此,通信看起来是这样的:

var
  NewData  : String;
begin
  TMotileThreading.ExecuteThenCall (
    procedure
    begin
      NewData := IdTCPClient.IOHandler.Readln;
    end,
    procedure
    begin
      GUIUpdate (NewData);
    end);
 end;

在执行和ExecuteThenCall方法简单地创建一个工作线程,设置FreeOnTerminate为true以简化存储器管理和执行所提供的功能的工作线程的执行和OnTerminate程序。

希望有所帮助。

修改(适用的要求充分执行类TMotileThreading的)

type
  TExecuteFunc = reference to procedure;

  TMotileThreading = class
  protected
    constructor Create;
  public
    class procedure Execute (Func : TExecuteFunc);
    class procedure ExecuteAndCall (Func : TExecuteFunc; OnTerminateFunc : TExecuteFunc;
                                SyncTerminateFunc : Boolean = False);
  end;

  TMotile = class (TThread)
  private
    ExecFunc             : TExecuteFunc;
    TerminateHandler     : TExecuteFunc;
    SyncTerminateHandler : Boolean;
  public
    constructor Create (Func : TExecuteFunc); overload;
    constructor Create (Func : TExecuteFunc; OnTerminateFunc : TExecuteFunc;
                        SyncTerminateFunc : Boolean); overload;
    procedure OnTerminateHandler (Sender : TObject);
    procedure Execute; override;
  end;

implementation

constructor TMotileThreading.Create;
begin
  Assert (False, 'Class TMotileThreading shouldn''t be used as an instance');
end;

class procedure TMotileThreading.Execute (Func : TExecuteFunc);
begin
  TMotile.Create (Func);
end;

class procedure TMotileThreading.ExecuteAndCall (Func : TExecuteFunc;
                                                 OnTerminateFunc : TExecuteFunc;
                                                 SyncTerminateFunc : Boolean = False);
begin
  TMotile.Create (Func, OnTerminateFunc, SyncTerminateFunc);
end;

constructor TMotile.Create (Func : TExecuteFunc);
begin
  inherited Create (True);
  ExecFunc := Func;
  TerminateHandler := nil;
  FreeOnTerminate := True;
  Resume;
end;

constructor TMotile.Create (Func : TExecuteFunc; OnTerminateFunc : TExecuteFunc;
                            SyncTerminateFunc : Boolean);
begin
  inherited Create (True);
  ExecFunc := Func;
  TerminateHandler := OnTerminateFunc;
  SyncTerminateHandler := SyncTerminateFunc;
  OnTerminate := OnTerminateHandler;
  FreeOnTerminate := True;
  Resume;
end;

procedure TMotile.Execute;
begin
  ExecFunc;
end;

procedure TMotile.OnTerminateHandler (Sender : TObject);
begin
  if Assigned (TerminateHandler) then
    if SyncTerminateHandler then
      Synchronize (procedure
                   begin
                     TerminateHandler;
                   end)
    else
      TerminateHandler;
end;

其他提示

您是在正确的轨道上。印地是要像使用。它使用的阻止套接字的,所以ReadBytes调用不返回,直到它的读取你问什么。对比,与非阻塞的套接字,其中一个调用可能会提前返回,所以你要么投票或得到通知异步确定何时请求已经被填满。

印地被设计以期望的插座的对象具有它们自己的线程(或纤维)。 Indy以附带TIdAntifreeze谁想要拖放插座组件安装到自己的表单和数据模块,并从主界面线程使用Indy组件的人,但是这并不是一个好主意,如果你能避免它。

由于您的线程不能没有工作FSocket被分配,我劝你简单地收到在类的构造函数值。断言在构造函数中,如果它不分配。此外,它是一个的错误的创建你的线程非悬挂,那么为什么连给的选项? (如果该线程不创建挂起,那么它会开始运行,检查FSocket是否分配,并失败,因为创建线程还没有得到分配该字段尚未。)

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top