INDY 10 IDTCPClient قراءة البيانات باستخدام موضوع منفصل؟

StackOverflow https://stackoverflow.com/questions/554142

سؤال

سؤال: ما أبحث عنه هو الأكثر نموذجية أو أفضل الممارسات طريقة لاستخدام مؤشر ترابط منفصل لتلقي البيانات باستخدام IDTCPClient في Indy 10.

خلفية: الرمز أدناه هو عينة من ما أحاول القيام به مع أجزاء معالجة البيانات الفعلية التي تمت إزالتها للوضوح. تتمثل فكرة الخيط في تلقي جميع البيانات (حجم متغير باستخدام رأس إعلان بقية طول الرسالة) وبالتالي لتحليله (هذا ما يفعله إجراء 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;

كادئة، استخدمت سؤال آخر Stackoverflow يتعامل مع مكونات الخادم INDY: "دلفي 2009، Indy 10، Tidtcpserver.Onexecute، وكيفية الاستيلاء على جميع البايتات في InputBuffer"للحصول على أساس ما لدي حتى الآن.

شكرا على اي مساعدة!

هل كانت مفيدة؟

المحلول

إذا كنت ترغب في تجنب النفقات العامة المفروضة عن طريق إنشاء فئات مؤشرات الترابط لكل تبادل بيانات خادم عميل، فيمكنك إنشاء فئة خيوط موتيل كما هو موضح في

http://delphidicas.blogspot.com/2008/08/anonymous-methods-when-should-they-be.html.

قضيت نفس المشكلة قبل بضعة أيام، لقد كتبتني للتو أداة إهاباء تفريخ فئة لديها وظائف ثابتة تسمح لي بإنشاء خيوط باستخدام ميزة الطريقة المجهولة الجديدة من 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;

طريقة التنفيذ و EXPLECETHENCALL طريقة إنشاء مؤشر ترابط عامل، اضبط FreeOnterminate على تبسيط إدارة الذاكرة وتنفيذ الوظائف المتوفرة في تنفيذ مؤشر ترابط العامل وإجراءات Ontermine.

امل ان يساعد.

تعديل (حسب الطلب التنفيذ الكامل للفئة TMoteilethreading)

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 من مؤشر ترابط Gui الرئيسي، ولكن هذه ليست فكرة جيدة عموما إذا كنت تستطيع تجنب ذلك.

منذ الخيط الخاص بك لا يمكن أن تعمل دون FSocket يتم تعيينك، أنصحك ببساطة تلقي هذه القيمة في منشئ الفصل. أكد في المنشئ إذا لم يتم تعيينه. علاوة على ذلك، هو خطأ لإنشاء مؤشر ترابطك غير معلق، فلماذا حتى إعطاء الخيار؟ (إذا لم يتم إنشاء الخيط معلق، فستبدأ التشغيل، والتحقق من ذلك FSocket تم تعيينه، وتفشل لأن مؤشر ترابط إنشاء لم يحصل على تعيين هذا الحقل حتى الآن.)

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top