الفريق العربي للبرمجةأرشيف المنتديات · 2000 – 2023
نسخة أرشيفية للقراءة فقط — التسجيل والمشاركة مغلقان، والمحتوى محفوظ كما كان.

الثريد في البرمجة غرضية التوجه:

مغلق
بدأه amersy في 27 مارس 2005 · 3 رد · 1,183 مشاهدة · في لغة Delphi
مشاركة: واتساب X فيسبوك تيليجرام
#1 صاحب الموضوع

الثريد في البرمجة غرضية التوجه:

تشغل البرامج عادة* عملية معالجة واحده (بروسس) يمكن أن تظهر في نافذة إدارة مهام ويندوز(تاسك مانيجار) حيث أن البرنامج هو عبارة عن سلسلة من أوامر الآلة (ماشين كود) التي قد تمت ترجمتها بالأصل من لغة البرمجة عالية المستوى مثل دلفي مثلا. حيث يتم تنفيذ الأوامر على مبدأ الرتل حيث لا تنفذ أي تعليمة حتى تنفذ التعليمة التي قبلها في الرتل المتوضع في ذاكرة ال(كاش) الخاصة بالمعالج و يمكن أن نستخدم أكثر من رتل أو مسار(ثريد) و عادة ما يستخدم المبرمجون مسارا واحدا فقط لتنفيذ البرامج و لكن في حال كنا نريد تنفيذ عمليتين مختلفتين في نفس الوقت في هذه الحالة سنلجأ إلى مسارات المعالجة المتعددة(مالتي ثريدينغ) و هنا أنا بصدد شرح كيفية عمل ذلك في دلفي.

* ممكن أن يكون أكثر من بروسس (نظام يونكس أول من دعم هذه الميزة ثم لحقه ويندوز فيما بعد).

أولا كانت المشكلة أنني أردت أن أستخدم طابعتين لطباعة فواتير معينة في مكانين مختلفين و بنفس الوقت و لعدد كبير من العمليات (ترانزاكشنس) فبمجرد إعطاء أمر الطباعة يجب أن تتم الطباعة على عدد غير محدد من الطابعات و بنفس الوقت.

فكان الحل مع ال(ثريدينغ) حيث قمت بكتابة الصنف(Class) التالي:

  
TPrintThread = class(TThread(
  
private
   fStr   : String;
   fPort : String;
  
protected
    procedure Execute; override;
    procedure LPT_PRINT;
    Procedure COM_PRINT;
  
public
    constructor Create(pStr, pPort):String;
  end;

قسم (البرايفيت)

حيث تمت وراثة الصنف ( TPrinterThread ) من الصنف الأب (TThread )

ثم قمت بتعريف متحولين (ڤاريبلس) ( fStr ) للنص الذي أردت طباعته و ( fPort ) لتحديد المنفذ الذي تتصل فيه الطابعة فيما إذا كان ( COM ) أو ( LPT ).

و تم التعريف في قسم ال(برايفيت) لأني لا أريد أن يصل و يعدل هذين المتحولين أي إجرائية من خارج الصنف.

قسم (البابليك)

في قسم (البابليك) الإجرائية المطلوبة هنا هي إجراء البناء (Constructor Create) حيث سنمرر القيم المرادة للمتحولات الموجودة في قسم (البرايفيت) إلى الغرض (Object) الذي تم خلقه من الصنف (TPrinterThread) كبارامترات لإجراء البناء.

constructor TPrintThread.Create(pStr, pPort: String);
begin

   fPort := pPort;
   fStr  := pStr;

   inherited Create(False);

end;

حيث تمت عملية إسناد البارامترات إلى المتحولات الداخلية للصنف (TPrinterThread) السطر الثالث حيث (inherited) عبارة عن استدعاء الإجراء المذكور بعدها لكن ليس من الصنف نفسه(TPrinterThread) و إنما من الصنف الأب (TThread) بدون هذا الإستدعاء لن يتم خلق أو إنشاء أي ثريد و الباراميتر الممرر هو (false) لا داعي للخوض فيه حيث يمكنك أن تمرره كما هو مذكور هنا تماما حيث أنه له علاقة بالبارامترات الممررة لإجراء ال(API) المسؤول عن خلق الثريد.

قسم (البروتيكتيد)

في قسم (البروتيكتيد) الإجرائية الرئيسة هي (Execute) يجب أن تكون موجودة حيث سيتم تنفيذ ما نريد من الثريد أن تفعل ضمن هذه الإجرائية.

procedure TPrintThread.Execute;
begin

   inherited;
   
   IF fPort = 'COM' Then   COMMPRINT
   Else
   IF fPort = 'LPT' Then    LPTPRINT;

end;

حيث (inherited;) لوحدها تعني (inherited Execute;) حيث قلت سابقا أن الإنهيريتيد عادة ما تستخدم لاستدعاء إجرائية من الصنف الأب يتم وضع اسمها بعدها و لكن في حال كنا نريد أن نستدعي نفس الإجرائية من الصنف الأب عندها لابد أن تكون الإجرائية الأب وهمية في حالتنا هنا (TThread) حيث تم تعريف هذه الإجرائية على الشكل التالي :

{TThread}
procedure Execute; virtual; abstract;

حيث (virtual) تعني أن الإجراء وهمي يمكن أن يتم إعادة كتابته في الصنف الإبن و له جسم في الصنف الأب

و (abstract) تعني أنه مجرد تعريف إجراء (proto-type) في الصنف الأب و ليس له جسم فيه و إنما جسمه يمكن كتابته في الأصناف الإبن.

و من ثم يجب وضع(override) كموجه للترجمة (Directive) عند نهاية تعريف الإجراء (Execute) في الصنف الخاص بي (TPrinterThread)

{TPrinterThread}
    procedure Execute; override;

الآن و حسب البراميتر الممرر إلى (باني الصنف) -إجرائية البناء للصنف – و التي تم حفظها في متحولات في قسم (البرايفيت) يتم إختيار فيما إذا كنا سنستخدم المنفذ (COM) أو (LPT) و بناءا على ذلك فإنه سوف يتم استدعاء أحد الإجرائيتين (COM_Print) أو (LPT_Print)

procedure TPrintThread.LPTPRINT;
var
  F: TextFile;              vPort : String;
begin

  Try

    vPort := vRec_Prntr.PORT;
    AssignFile(F,vRec_Prntr.PORT);
    Rewrite(F);
    WriteLn(F,fStr+#$0D);

  Finally
    CloseFile(F);
  End;

end;

procedure TPrintThread.COMMPRINT;
begin
  DMod.ComPort_Prntr.Open;
  DMod.ComPort_Prntr.WriteData(fStr+#$0D);
  DMod.ComPort_Prntr.Close;
end;

حيث أن الإجراءين الأول واضح و الثاني عبارة عن كومبوننت كنت قد كتبته سابقا للتعامل مع المنافذ التسلسلية لسنا بصدد الحيث عنه الآن.

الآن و كصنف فهو جاهز أما طريقة الإستخدام فهي كالتالي:

أولا نعرف متحولا عاما

Var
  ThreadsRunning: Integer;

لمعرفة عدد الثريدات التي تعمل, حيث أنه قبل أي استدعاء إجراء بناء الثريد للصنف (TPrinterThread) يجب زيادة هذا المتحول بواحد

inc(ThreadsRunning);

و بعد التنفيذ الثريد يتم استدعاء إجراء يقوم بإنقاص هذا المتحول بمقدار واحد.

procedure ThreadDone(Sender: TObject);
begin

  Dec(ThreadsRunning);

end;

يمكن تعريف هذا الإجراء في أي مكان تستطيع إجرائية التنفيذ الوصول إليه و إليكم الآن إجرائية التنفيذ و كلاهما ليسا بأعضاء في الصنف (TPrinterThread).

Function Receipt_Print_Com(vStr : String): byte;
Begin

  ThreadsRunning := 2;

  Try
     // for the first printer
     With TPrintThread.Create(vStr,'COM') Do OnTerminate := ThreadDone;
     
     //for the second Printer
     With TPrintThread.Create(vStr,'LPT') Do OnTerminate := ThreadDone;

  Except
     // error message
  End;

end;

الشام الله حاميها...

أنا الدمشقيُّ.. لو شرحتمُ جسدي

لسـالَ منهُ عناقيـدٌ.. وتفـّاحُ

و لو فتحـتُم شراييني بمديتكـم

سمعتمُ في دمي أصواتَ من راحوا

مآذنُ الشّـامِ تبكـي إذ تعانقـني

و للمـآذنِ.. كالأشجارِ.. أرواحُ

#2

مقالتك أصيلة amersy ..

أنا بغاية السعادة لدعمك لمواضيع مشابهه في المنتدى .. ربما قل ماتجد في المنتدى كلام عنها

شكرا لك , و أنتظر منك المزيد

#3

موضوع جميل اخي amersy. فكما قال عروة نحن بحاجة لمواضيع توضح وتفصل طريقة التعامل مع Process و Threads وكذلك كيفية تعريف أحداث جديدة و إدارتها و التعامل مع Messages Method. :rolleyes:

سأحاول أن أكتب عنها في الأسبوع المقبل إذا لم يكتب أحد الأخوة شيئ بخصوصها :lol:

سأتغيب عن المنتدى وستكون لي زيارات خفيفة بين الحين و الحين

يا صاحب الهم إن الهم منفرج.....................أبشر بخير فإن الفارج الله.

اليأس يقطع أحيانا بصاحبه..........................لا تيأس فإن الكافي الله.

الله يحدث بعد العسر ميسرة.........................لا تفزعن فإن الصانع الله.

إذا بليت فثق بالله وارض به...................فإن الذي يكشف البلوى هو الله.

و الله ما لك غير الله من أحد.......................فحسبك الله في كل لك الله

أخوكم مراد

27_06_06_05_21_41_1151410901logo_adl_wal_ihsan.jpg

#4

يالله مراد ..

شعلها ..

أاااه ... المشكلة انني أستلمت عدة مشاريع (طبعا دلفي) وأنا الآن أعمل بجد وهذا ماقد يعرقل سرعتي بالكتابة قليلا , على كل حال لابأس سأستفيد من كامل وقت الفراغ لدي للإنترنت

هذا الموضوع مغلق.

مواضيع مشابهة