delphi4arab منتديات دلفي للعرب

نسخة كاملة : دلفي & threads مفاهيم و تطبيقات .
أنت حالياً تتصفح نسخة خفيفة من المنتدى . مشاهدة نسخة كاملة مع جميع الأشكال الجمالية .
الصفحات : 1 2
بسم الله الرحمان الرحيم
السلام عليكم و رحمة الله و بركاته

كيف نبرمج تطبيقاتنا بطريقة حديثة ؟ , كيف يمكن لنا أن نسرع من أداء برنامجنا دون وقوع مشاكل أو :frusty: , كيف لنا أن تشغيل عدة عمليات
في آن واحد (ظاهريا) بالتوازي و بشكل متزامن (مدروس) ؟ , ببساطة البرمجة بالإعتماد على آلية Multi_Thread .

بعض التوضيحات "نظريا" :
أنظمة التشغيل تتوافق تماما مع هندسة المعالج و آلياته , الأنظمة الحديثة (Multi_Tache) أساسا تعتمد على تقليص زمن التنفيذ كيف ؟
عن طريق آلية Pipeline, معالج يدعم pipeline ينفذ تعليمات برنامج ما "بالتزامن في طور عمل واحد" وفق روتينا المعالج :
Fetch,decode,memory access,write back لاحظ الجدول التالي الدي يوضح آلية معالجة برنامج بـ Pipeline

[صورة: 1561g.jpg]

نفرض مثلا أن لدينا برنامج 20 %تعليمات تحميل و تخزين , 40 %تعليمات منطقية و مقارنة ... , 40 %تعليمات قفز و تفرع ...
لو كان المعالج لا يدعم pipeline سيظطر لتنفيذ تعليمة بعد تعليمة و لن يدخل للتعليمة الجديدة حتى ينهي السابقة ! و إذا كان كل صنف
من التعليمات يحتاج طورين أو أكثر لتنفيذ التعليمة الواحد لك أن تتخيل "مدى بطئ معالجة تعليمات البرنامج المحمل الواحد" لكن مع pipline
أطوار عمل أقل و أداء أسرع يمكن أن ننفذ أكثر من برنامج (Process) بشكل متزامن (Synchronize) بإزاحة توافق (Priority) المخصصة
لكل process على أساس Pid(رقم تعريف البروسس), hProcess(مقبض البروسس), لم أشرح كثيرا فقط صطحيا للدخول في جو الدرس ! .

"الان ماذا لو قمنا بنفس عمل نظام التشغيل داخل تطبيقاتنا ؟ يعني أن ننفذ العديد من العمليات بشكل متزامن في آن واحد (ظاهريا) !."

الشكل العام لإنشاء thread واحد كمثال أول , نعتمد على خصائص البرمجة poo بشكل عادي يعني إنشاء
class
مورث من TThread في ديلفي .

PHP كود :
{$IFDEF VER150}//delphi 7
Type
 MyThread 
= Class (TTHread)
 Private
  
_i:Byte;
 Protected
  
Procedure DoSomeThing;
  
Procedure Execute;OverRide;
 Public
  
Constructor Create (Suspended:Boolean);
  
Destructor Destroy;OverRide;
 
End;
{
$ENDIF}

var
  
MainFrm: TMainFrm;
  
MyTh :MyThread;

implementation

{$R *.dfm}

Constructor MyThread.Create;
Begin
Inherited Create
(Suspended);//If False = start when we call create constructor !.
_i:= 0;//Initialization ...
End;

Destructor MyThread.Destroy;
Begin
//Set Object That Created Free ...
Inherited;//Call the oroginal Destructor (TThread Class).
End;

Procedure MyThread.Execute;
Begin
 repeat
   Sleep
(100); //500 = 1/2 s
   
Synchronize(DoSomeThing);
  
until Terminated;
End;

{
$X+}// Set extended syntax on

Procedure MyThread.DoSomeThing;
Begin
Inc
(_i);
If 
_i <= 255 Then
MainFrm
.Label3.Caption:= IntToStr(_i) Else
 
_i:= 0;
End;

procedure TMainFrm.Button1Click(Sender: TObject);
begin
 MyTh
:=MyThread.Create(False);
end;

procedure TMainFrm.Button2Click(Sender: TObject);
begin
Try
 
MyTh.Suspend;
Except
 On E 
: Exception Do
  
MessageBoxA(0,Pchar(E.Message),Nil,0);
 
End;
end;

procedure TMainFrm.Button3Click(Sender: TObject);
begin
Try
 
MyTh.Resume;
Except
 On E 
: Exception Do
  
MessageBoxA(0,Pchar(E.Message),Nil,0);
 
End
end
;

procedure TMainFrm.Button4Click(Sender: TObject);
begin
 MyTh
.Terminate;
 
//finalization ...
 
Label3.Caption:= '0';
 
MainFrm.Button1.Enabled:= True;
end;

procedure TMainFrm.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
begin
 Button4Click
(Sender);// THread Must Be Terminated!.
 
ExitProcess(GetLastError);//Exit .
end;

initialization
 MyTh
:=MyThread.Create(True);
finalization
 MyTh
.Free;
end. 
التوجيه IFDEF هنا أظفته متعمدا لتحديد إصدار دلفي المعتمد في التطبيق يمكن تجاوزها (إظافة فقط) كما أني أظفت التوجيه $X
الدي يتيح لنا دمج الدوال و الإجراءات دون مراعات ترتيب الـ implementation (أيضا كإظافة:tongSmile
,
قمنا بإدراج initialization / finalization يكفي أن نعمل Resume لبدأ تنفيذ Execute الخاص بالـ Thread آليا !
.

- هناك عشرات التعريفات و المقدمات حول موضوع الـ THread لذا كان علي الدخول من منطلق
أخر , هدا
التطبيق الأول مثال بسيط للمناقشة ....

[صورة: myapp.gif]
. في هذا المثال قمنا ببرمجة عداد بسيط لن تنجح في تنفيذه دون إستعمال الـ threads! , هنا لم يتجمد البرنامج (freeze)
& النتيجة دورية 1/10 ثانية & تحكم أكثر & أداء أحسن (مثلا إستغنينا عن الـ Timer).
اخي الكريم TF6M بارك الله فيك على هكذا درس . و لكن هناك ملاحظة :

لماذا انشئت ال Thread في ال [FONT=Simplified Arabic Fixed]initialization وحررته في ال finalization
[FONT=Simplified Arabic Fixed]:


كود :
[COLOR=#0000bb][FONT=Simplified Arabic Fixed][COLOR=#0000bb]initialization[/COLOR] [FONT=Simplified Arabic Fixed][COLOR=#0000bb]MyTh[/COLOR][COLOR=#007700]:=[/COLOR][COLOR=#0000bb]MyThread[/COLOR][COLOR=#007700].[/COLOR][COLOR=#0000bb]Create[/COLOR][COLOR=#007700]([/COLOR][COLOR=#0000bb]True[/COLOR][COLOR=#007700][FONT=Simplified Arabic Fixed]);[/COLOR] [FONT=Simplified Arabic Fixed][COLOR=#0000bb]finalization[/COLOR] [FONT=Simplified Arabic Fixed][COLOR=#0000bb]MyTh[/COLOR][COLOR=#007700].[/COLOR][COLOR=#0000bb]Free[/COLOR][FONT=Simplified Arabic Fixed][COLOR=#007700];[/COLOR] [FONT=Simplified Arabic Fixed][COLOR=#0000bb]end[/COLOR][COLOR=#007700]. [/COLOR][/COLOR]


ثم صرحت بانشائه في الحدث OnClick للزر :

كود :
[FONT=Simplified Arabic Fixed][COLOR=#0000bb]procedure TMainFrm[/COLOR][COLOR=#007700].[/COLOR][COLOR=#0000bb]Button1Click[/COLOR][COLOR=#007700]([/COLOR][COLOR=#0000bb]Sender[/COLOR][COLOR=#007700]: [/COLOR][COLOR=#0000bb]TObject[/COLOR][COLOR=#007700][FONT=Simplified Arabic Fixed]);[/COLOR] [FONT=Simplified Arabic Fixed][COLOR=#0000bb]begin[/COLOR] [FONT=Simplified Arabic Fixed][COLOR=#0000bb]MyTh[/COLOR][COLOR=#007700]:=[/COLOR][COLOR=#0000bb]MyThread[/COLOR][COLOR=#007700].[/COLOR][COLOR=#0000bb]Create[/COLOR][COLOR=#007700]([/COLOR][COLOR=#0000bb]False[/COLOR][FONT=Simplified Arabic Fixed][COLOR=#007700]);[/COLOR] [FONT=Simplified Arabic Fixed][COLOR=#0000bb]end[/COLOR][COLOR=#007700];[/COLOR]



اقصد ان اقول ان ال Thread قد تم انشاءه مع ال [FONT=Simplified Arabic Fixed]initialization فقط Suspended .
[FONT=Simplified Arabic Fixed]
[FONT=Arial]شكرا بارك الله فيك ,,

1- لن أناقش مسئلة التحريرSmile بل
[FONT=Arial]initialization
هنا لكي نبدأ بإستعمال الـ Thread مباشرة
[FONT=Arial]لا حظ الـ Start غير مفعلة!
2- قمت بإعادة التصريح ببساطة لإعادة العملية , في حالة
إيقاف الـ Thread بـ Terminate

[FONT=Arial]initialization / [FONT=Arial]finalization عوض إعادة الإنشاء و التحرير
في بداية و نهاية عمل الـ Thread ؟ .

3- نعم قمت بإنشاء الـ Thraed كـ
[FONT=Simplified Arabic Fixed][FONT=Arial]Suspended [FONT=Arial]فقط لإرجاع
أمر بدء تنفيذ
[FONT=Arial]Execute [FONT=Arial]لنا (لو كان False لبدأ العد مباشرة
بعد التنفيذ) .

ولكن اخي الكريم TF6M هنا سيحدث Thread Collison في حالة تم الظغط على [FONT=Simplified Arabic Fixed]Button1 لانه سوف يتم انشاء نفس ال Thread يمكن ان يكون باHandle جديد و لكن سوف يتم انشاءى و هذا ماسيحدث خلل في تحريره مرة اخرى لا ال OS لايعرف اي Thread سوف يتم تحريره انطلاقا من ال المقبض او ال HANDLE
[FONT=Simplified Arabic Fixed]حاول مثلا عدم استعمال :
[FONT=Simplified Arabic Fixed]
كود :
[COLOR=#0000bb][COLOR=#0000bb]ExitProcess[/COLOR][COLOR=#007700]([/COLOR][COLOR=#0000bb]GetLastError[/COLOR][COLOR=#007700]);[/COLOR][COLOR=#ff8000]//Exit [/COLOR][/COLOR]
[FONT=Simplified Arabic Fixed].
[FONT=Simplified Arabic Fixed]
[FONT=Simplified Arabic Fixed]انت انشئت ال Thread مع ال [FONT=Arial]initialization ولكن SUSPENDED ثم انشئته مرة اخرى و لكن في انتظار او Resuming .اذا كان يمكن القيام بكل هذه العمليم هكذا مثلا :
[FONT=Arial]
كود :
procedure TMainFrm.Button1Click(Sender: TObject); begin MyTh:=MyThread.Create(False); //.. //do what ever //.. //.. MyTh.resume; end;
وعليكم السلام ورحمة الله وبركاته
TF6M واليوم الخميس حان وقت درس نفيس Smile
@Mohfa
أولا رد السلام Big Grin
ثانيا: علينا أن نبتعد عن التفاصيل التي لن يفهمها كل من يدخل قسم "دروس دلفي للمبتدئين" لا تنسوا.

إقتباس :لماذا انشئت ال Thread في ال initialization وحررته في ال finalization
صح... أنا أيضا ظننت في البداية أنه قام بإنشاء thREad مرتين، وعندما حملت المثال اتضح خلاف ذلك Smile
فالزر Button1 غير مفعل، حتى يتم Terminate للـ Thread.

كنت أعددت مثال صغير لتوضيح مفهوم Threads للمبتدئين، وبعد إذن أخي TF6M سأضيف توضيحات.
كود :
http://i42.tinypic.com/opyeww.jpg
حاول النقر على Go no Thread ثم ShowMessage مباشرة
الآن، حاول النقر على Exec Thread ثم على ShowMessage مباشرة
الفرق واضح Smile
مبدئيا... Thread هي Process يقوم النظام بتشغيلها عوضا عن برنامجك، وبذلك تستفيد من مزايا زيادة السرعة واقتصاد الذاكرة.

كل Thread له priority تعني أولوية الـ Thread في النظام (وهذا مهم حالة وجود العديد منها).

تنبيه للمبتدئين: حذار الـ Threads ليست للعب! وينبغي التعامل معها بحذر.
مثال مرفق.

ملاحظة: في نسخة دلفي 2010 تم إضافة الأمر Start.
وشكرا على الدرس الرائع
وشكرا لتدخلات الأستاذ Mohfa
تحياتي.
السلام عليكم
بارك الله فيك أخي TF6M
جاء الدرس في الذي أدرس فيه :rtfm2:
في المارة القادمة إن أمكن أخي العزيز التعمق أكثر :monster2:
أخي كاش واحد لا تنسى درس المؤشرات، أنتظرك
اولا السلام عليكم و رحمة الله و بركاته .

إقتباس :[FONT=Arial]كما قلت لك أعدت إنشاءه فقط في حالة إيقافه يعني لا يمكن أن ننشأه مرتين

ولكن ياخي الكريم TF6M اين شرط التاكد من عدمه قبل الانشاء من جديد .
ثانيا حتى و لو كنت قد تاكدت من التوقف من الاحسن تحرير ال Thread قبل انشائه مرة جديد يعني استطيع ان استعمل مثلا :
كود :
if terminated then free
لقول مثلا .

كود :
[COLOR=#0000bb]ExitProcess[/COLOR][COLOR=#007700]([/COLOR][COLOR=#0000bb]GetLastError[/COLOR][COLOR=#007700]);[/COLOR][COLOR=#ff8000]//Exit [/COLOR]

هكذا تجبر النظام ان يوقف التطبيق مهما كانت النتائج حتى باستعمال GetLastError
هنا تقول MS من خلال ال msdn ليس من المستحسن استعمال ال ExitProcess مع ال Threads hاو ال Pip lining لماذا :

يمكن ان يكون هناك Infinit او عملية غير منتهية او مايدعى ال Long Process اذا استعملنا ال ExitProcess فهذا سيجبر التطبيق على التوقف مهما كانت النتائج , ومن بين النتائج الخطيرة هي ال System او Memory instability .
في حالتك يمكن استعمال ال Waitfor و هذا سوف يجبر ال Thread التحقق من اي Operation غير منتهية او من عدم تفريغ ال Quee وهذا سوف يحرر كل ال Ressources قبل تحرير ال Thread

اقول و اعيد انك تقوم بانشاء ال Thread مرتين لماذا تتبع معي ال المشهد :

1* عند بداء التطبيق يتم انشاء ال Thread و لكن Suspended يعني بانتطار اي عملية .
2* عندما اظغط على الزر 2 هذا سوف يقوم بتوقيف ال Thread لزمن معين او Suspended .
3* عندما اظغط على الزر 3 هذا سوف يقوم باعادة تشغيل ال Thread بعدما كان Suspended .
4* عندما اظغط على الزر 4 هذا سوف يقوم بتوقيف ال Thread و انهائه و لكن ليس تحريره يعني ال Handle مازال موجود و ال Ressources مازالت في ال Thread Quee .
*5 عندما اظغط على الزر Start ماذا سيحصل ياترى :
سوف يتم اعادة انشاء نفس ال Thread و الذي اصلا مازال موجود و لم يتم تحريره .

6* OnCloseQuery :
سوف يتم مناداة ال المرحلة 4 و يتم غلق التطبيق . رغم ان ال Thread مازال موجود في الذاكرة اقصد مازال الحيز Reserved .

اذا اما ان نستعمل ال :
FreeOnTreminate في وقت الانشاء مع :
كود :
Constructor MyThread.Create; Begin Inherited Create(Suspended);//If False = start when we call create constructor !. _i:= 0;//Initialization ... End;
او نتاكد من تحريره في وقت الهدم :
مع : If terminated then free .
او نستعمل ال Waitfor ثم ال free .

لان terminate لا تحرر ال Thread بل توقفه عن العمل .

انظر هنا مثلا
كود :
https://forums.codegear.com/message.jspa?messageID=142218

اتمنى ان الفكرة وصلت .

بارك الله فيك و في اخي kachwahed و كل الاعضاء .

و السلام عليكم
الفكرة كلها تتمحور حول إعادة إنشاء الـ Thread دون التأكد من تحريره Smile

1- عند غلق البرنامج سيحرر عندالإنهاء , Finalization
2- أقول و أعيد هدا التطبيق الأول , هناك ما يسمى بـ Blocking & Premature Termination
و هي تدخل في الأخطاء التي يقع فيها المبرمج التي يمكن تفاديها بـ Method waitfor
3- أيضا سأتتطرق لـ عيوب التزامن Disadvantage Synchronizer في التطبيق .

- حل هذه المشكلة فقط بإظافة شرط التحرير عند أمر الإنهاء :

PHP كود :
Constructor MyThread.Create;
Begin
Inherited Create
(Suspended);//If False = start when we call create constructor !.
FreeOnTerminate:= False;
_i:= 0;//Initialization ...
End; 
و حدف
OnCloseQuery أصلا ,,

بارك الله فيك على الإهتمام & الإفادة , شكرا.
في نسخة Delphi 2010 يمكن كتابة إجراء Synchronize كما يلي:
PHP كود :
Procedure MyThread.Execute;
Begin
 repeat
   Sleep
(100); //500 = 1/2 s
   
Synchronize( Procedure ()
                
Begin
                Inc
(_i);
                If 
_i <= 255 Then
                MainFrm
.Label3.Caption:= IntToStr(_i) Else
                 
_i:= 0;
                
End);
  
until Terminated;
End; 
بالتوفيق أخي TF6M.
بسم الله الرحمان الرحيم

تعريف الـ Thread:
- العديد من البرامج (خاصة الحديثة منها) تعتمد على تقنية الـ MultiThreading , هل من الممكن أن نأكل و نشرب و نجري في آن واحد :whistling:!؟ دون عوائق.
الـ thread عبارة عن برنامج (Sous_Programe) , وحدة تنفيذ مستقلة , تتكرر بشكل غير منتهى (حلقة) الى أن يتم إنهائها (Terminate)
يتم تنفيدها من طرف نظام التشغيل على أساس : رقم التعريف (threadID) , أولوية التنفيذ (thread Priority) , مقبض الثريد (thread Handle) .
كما يمكن تعمل عدة threads في آن واحد في برنامج ما , لتحسين أداء & سرعة تنفيذ البرنامج .

التطبيق الثاني :

- برنامج يقوم بقراءة ملف ما Byte By Byte & يعرض بشكل متزامن القيمة المقروؤة & و نسبة القراءة بالنسبة للملف .
- نفس التطبيق السابق من حيث الفكرة , لكن بشكل عملي أحسن :thumbs: .

[صورة: 51651.gif]

بالتوفيق ,,
الصفحات : 1 2