طيب دعنا نقرأ بداية هذا المقال من موقع About
إقتباس :To update your application's user interface - main thread - from a secondary thread you need to call the Synchronize method - a thread-safe method that avoids multi-threading conflicts that can arise from accessing object properties or methods that are not thread-safe, or using resources not in the main thread of execution.
الخلاصة عندما نريد أن نعمل تحديث لل GUI و التي هي Main Thead من Thread أخر يجب علينا استدعاء Synchronize Method لكي لايحدث مشاكل كالتي حدثت معك
و دعنا نقرأ هذه المقالة من موقع embarcadero
Why synchronize?
إقتباس :When a thread is running, it runs on its own without wondering what other threads are doing. That is why one thread can calculate a sum of two numbers -- let's say a and b, while another thread comes to life and changes the value of a. This is not what we want! So we need a shell around the global variables so that no other thread can access them. Then, when the calculations are done, we might remove the shell to give other threads in the system access to the data once more.
The easiest way to construct such a shell is to use critical sections. We will use these as a start.
(Incidentally, synchronization bugs like this can bite you when you are using VCL components, which are generally not thread-safe. When you start updating controls from different threads everything may seem fine...but the bug will present itself some time in the future. Then it is up to you to find the synchronization bug. Believe me, this can take a while. Debugging threads is really frustrating!
الخلاصة المشاكل ستنتج حكما إذا كنا سنستخدم GUI مع MultiTHreading بدون أن نستخدم Synchronize
و هي أخر مقالة و هي عن ال Indy من أحد المطورين عن الأندي gambit47
إقتباس :TIdTCPServer is a multi-threaded component. It is not safe to directly access UI components from outside the main thread. Bad things can happen if you do - crashes, deadlocks, random memory corruption, etc. You must synchronize with the main thread whenever you want to update the UI. That has always been the case, even in earlier versions of Indy. You can use Indy's TIdSync or TIdNotify classes to help you
طيب الأن يجب علينا أن نعمل مزامنة بين ال Threads في حالة لدينا MultiThread Application و لكن كيف
في ال Indy العملية سهلة لأنه هناك طريقتين هما IdSync و ال IdNotify و الاثنان يقومان بنفس العملية بالنهاية و لكن هناك اختلاف وحيد (هي وظيفتك لتعرفو)
و الأن لنرجع لكود البرنامج
في الكود الأول هو المسؤول عن المزامنة ركز بالكود و سترى بأن ال Fmsg و Frnum موجودان في ال
TLogRoomSync و بالنسبة للاستدعاء الأساسي تجده في حدث OnExecute و الذي هو
كود :
TLogRoomSync.WriteMsg(RoomNum,_CC_UserName)
و تحليل الموضوع كالتالي
عندما بأتي الطلب من الكلاينت و بعبارة أدق عندما يستقبل السرفر ال String من الThread الخاص بالكلاينت و نريد عندجها اسقاط هذا ال String على ال GUI أو Main Thread عندها نستدعي هذا الكود
كود :
TLogRoomSync.WriteMsg(RoomNum,_CC_UserName)
و عندها نقوم بانشاء String في الكلاس TLogRoomSync اعتبرها وسيط تقوم بنقل المعلومات من Thread لأخر و لكن هذا أين يتم نعم إنه بالكود الأول
كود :
Class procedure TLogRoomSync.WriteMsg(N,S : String);
begin
with Create do
try
Fmsg := S;
Frnum := N ;
Synchronize;
finally
Free;
end;
end;
حيث يأخذ ال Fmsg الرسالة القادمة من الكلاينت و Frnum و هو عبارة عن رقم صحيح(في الكود الخاص بك يمثل رقم الغرفة) طبعا بعد انشائهما ب Create
ثم تتم عملية ال Synchronize و أخيرا يتم التحرير Free
و في إجرائية DoSynchronize تتم الكتابة في UI من الوسيطان Fmsg و Frnum
**** أن تكون الصورة وضحت و اكتملت
على فكرة برنامجي O-Helper في أخر اصدار له في الموقع تجد به هذه المشكلة التي أن تواجهها الأن و لكني حسنته كثيرا و أصبح ذو قدرة كبيرة مع واجهة جميلة و لكن ينقصه القليل و أقوم بنشر اصدار جديد مع مزايا جديدة.