مؤشر الترابط المخصص يسيء التصرف
-
22-12-2019 - |
سؤال
نظرا للفئات التالية:
type
GEvent = class(TThread)
public
procedure Terminate;
procedure Call(Event : GEvent);
constructor Create;
procedure Execute; Override;
end;
TDirection = (DUp, DRight, DDown, DLeft);
EventTitle = class(GEvent)
private
Index : Integer;
Sprite : CSprite;
Terminate : Boolean;
procedure CreateSprite;
procedure MoveCursor(Direction : TDirection);
procedure RefreshCursor;
constructor Create;
destructor Destroy;
public
procedure Execute;
end;
implementation
{ GEvent }
procedure GEvent.Call(Event: GEvent);
begin
Suspend;
// inherited Terminate;
Self := GEvent(Event.ClassType.Create);
end;
constructor GEvent.Create;
begin
inherited Create(True);
end;
destructor GEvent.Destroy;
begin
Terminate;
inherited;
end;
procedure GEvent.Execute;
begin
// inherited;
end;
procedure GEvent.Terminate;
begin
Suspend;
inherited;
end;
{ EventTitle }
constructor EventTitle.Create;
begin
inherited;
Resume;
end;
procedure EventTitle.CreateSprite;
begin
Showmessage('anything');
end;
destructor EventTitle.Destroy;
begin
inherited;
end;
procedure EventTitle.Execute;
begin
inherited;
Synchronize(CreateSprite);
Index := 0; {
while not Terminated do
begin
if GISystem.System.Input.Trigger(KUp) then
MoveCursor(DUp);
if GISystem.System.Input.Trigger(KDown) then
MoveCursor(DDown);
end; }
end;
عندما يستدعي النموذج الرئيسي InstanceVar := EventTitle.Create
يجب أن يصل الخيط تلقائيًا إلى الطريقة CreateSprite
, ، ما هو غريب لا يحدث.لم أتمكن من معرفة سبب عدم تنفيذ الطريقة.لا يزال النموذج الرئيسي للتطبيق يعمل بشكل جيد ولكن يبدو أنه EventTitle.Execute
يتوقف فجأة أو حتى لا يبدأ.وقد يكون سوء تنفيذ أيضًا.إنها أول تجربة لي لتقنية MultiThreading، لذا آسف على أي تضارب.يمكن لأي شخص أن يرى ما فعلته خطأ؟
المحلول
هناك بعض المشاكل الواضحة هنا.لست متأكدًا من أن إصلاحها سيحل مشكلتك، لكنني لن أتفاجأ:
- لك
Execute
يجب الإعلان عن الطريقة معoverride
لتشغيله.وهذا ما يفسر السلوك الذي تبلغ عنه. - يجب الإعلان عن المدمر الخاص بك باستخدام
override
لتشغيله.لاحظ أنك تنفذGEvent.Destroy
لكن الGEvent
لا تعلن الفئة عن المدمرة.لذلك لا يتم تجميع الكود الموجود في السؤال. - لا تتصل
Terminate
في المدمر لفئة الموضوع.المدمرة الطبقة الأساسيةTThread.Destroy
ينهي وينتظر الموضوع.إزالة المكالمة إلىTerminate
فيGEvent.Destroy
. - لك
Terminate
يخفي الأسلوبTThread.Terminate
.هذه ممارسة سيئة حقًا.أنا متأكد من أن المترجم يحذرك من هذا.يجب أن تستجيب للتحذيرات.أثناء وقوفه، يقوم مدمر الخيط الخاص بك بتعليق الخيط ثم ينتظر حتى ينتهي.من الأفضل أن تأمل أن يكون مؤشر الترابط قد انتهى بالفعل من التنفيذ بحلول الوقت الذي تقوم فيه بتدميره. - من غير المجدي إنشاء سلسلة رسائل معلقة فقط لاستئنافها على الفور.على الرغم من عدم وجود مشكلة حقيقية من شأنها أن تسبب ذلك.
- الكود في
GEvent.Call
هو زائف تماما.لا تعين لSelf
.يجب عليك إزالة هذا الرمز. - جميع مكالماتك إلى
Suspend
مخطئون.يجب أن لا تتصلSuspend
.لها نتائج غير متوقعة.إزالة المكالمات إلىSuspend
.
الخطأ المتكرر الذي قمت به هو إغفال override
.يتم استخدام هذه الكلمة الأساسية لتجاوز الطريقة الافتراضية.في حالة Execute
الطريقة والمدمرة، هذه طرق افتراضية تستدعيها فئة أساسية.على هذا النحو، إذا لم تقم بتجاوز الطريقة الافتراضية، فأنت ببساطة تقوم بإدخال طريقة جديدة في الفئة المشتقة.وعندما تستدعي الفئة الأساسية الطريقة الافتراضية، فلن يتم تنفيذ طريقتك الجديدة.
أقترح عليك أن تبدأ بهذا الكود:
type
EventTitle = class(TThread)
private
procedure DoSomething;
public
constructor Create;
procedure Execute; override;
end;
implementation
constructor EventTitle.Create;
begin
inherited Create(False);
end;
procedure EventTitle.DoSomething;
begin
ShowMessage('anything');
end;
procedure EventTitle.Execute;
begin
Synchronize(DoSomething);
end;
لقد قمت بحذف جميع التعليمات البرمجية الخاصة بك تقريبًا، ولكن معظمها كان خاطئًا.