Инди 10 IdTCPClient, Считывая Данные с помощью отдельного потока?

Потому что O является асимптотическим сравнением, которое отвечает на вопрос, как функция сравнивается для больших n. Нижние степени многочлена становятся несущественными для поведения функции, если n достаточно велико.

5
задан Community 23 May 2017 в 12:25
поделиться

2 ответа

Если Вы хотите избежать издержек, наложенных путем создания классов потока для каждого обмена данными клиент-сервер, Вы могли создать подвижный класс поточной обработки, как описано в

http://delphidicas.blogspot.com/2008/08/anonymous-methods-when-should-they-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 на истинный, чтобы упростить управление памятью и выполниться, обеспеченные функции в рабочем потоке Выполняются и процедуры 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;
8
ответ дан 18 December 2019 в 13:19
поделиться

Вы на правильном пути. Инди предназначается, чтобы использоваться как этот. Это использует блокирующиеся сокеты, таким образом, ReadBytes вызов не возвращается, пока он не читается, что Вы попросили. Контраст, что с неблокированием сокетов, куда вызов может возвратиться рано, таким образом, Вы или опрашиваете или уведомляетесь асинхронно для определения, когда запрос был заполнен.

Инди разработана с ожиданием, что объекты сокета имеют свои собственные потоки (или волокна). Инди идет TIdAntifreeze для людей, которые хотят перетащить компоненты сокета на их формы и модули данных и использовать компоненты Инди от основного потока GUI, но это обычно не хорошая идея, если можно избежать его.

Так как Ваш поток не может работать без FSocket быть присвоенным, я советую Вам просто получать то значение в конструкторе класса. Утверждайте в конструкторе, если это не присвоено. Кроме того, это - ошибка создать Ваш неприостановленный поток, итак, почему даже дают опцию? (Если поток не будет создан приостановленный, то он начнет работать, проверьте ли FSocket присвоен, и сбой, потому что поток создания не добрался для присвоения того поля все же.)

6
ответ дан 18 December 2019 в 13:19
поделиться
Другие вопросы по тегам:

Похожие вопросы: