كيف يمكنني تقليل النفقات العامة عند معالجة الرسائل في حلقة طويلة

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

  •  25-09-2019
  •  | 
  •  

سؤال

لقد حصلت على بعض الحلقات الطويلة ولكن البسيطة في برنامج Delphi الذي قد يحلق ملايين المرات ويستغرق تنفيذ بعض الثواني. الكود الموجود داخل الحلقة سريع للغاية وتم تحسينه. يستغرق وقتًا طويلاً لأنه يتم عدة مرات.

على سبيل المثال:

Screen.Cursor = crHourGlass;
R := FirstRecord;
while R <> nil do begin
  { do something simple with R.Value }
  R := R.NextRecord;
end;
Screen.Cursor := crDefault;

الآن لا أريد أن يكون برنامجي غير مستجيب ، لذلك أريد إضافة تطبيق. المعالجة داخل الحلقة. لكني أريد أيضًا أن تبطئ العبارات المضافة حلقيتي قدر الإمكان.

أتابع قائمة مرتبطة ، لذلك ليس لديّ متغير حساب متاح وسيضطر إلى إضافة واحدة إذا أردت فترات زمنية. أو يجب أن أضيف مؤقتًا ، لكنني بحاجة إلى تقليل الوقت للتسجيل.

كيف يمكنني تنفيذ هذا لتقليل النفقات العامة التي تمت إضافتها؟


خاتمة:

في الوقت الحالي ، أفعل شيئًا مثل إجابة APZ28.

ولكن يبدو أني على المدى الطويل يجب أن أقوم بتنفيذ نوع من الخيوط للتعامل مع هذا. شكرًا على توجيه هذا الأمر ، لأنني اعتقدت أن التطبيق. المعالجة هي الطريقة الوحيدة للقيام بذلك.

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

المحلول

هل يمكنك وضع حلقة العمل في سلسلة رسائل ، وتحرير الخيط الرئيسي لمعالجة حلقة واجهة المستخدم الرسومية.

نصائح أخرى

ضعه تحت الموضوع ليس ثلاثية لأنه يتطلب مورد مشاركة القفل إن وجد. خدعة جيدة تتمثل في وجود عداد ، بعد معالجة # من الحلقة ، وعملية الاتصال

var
  LoopCounter: Integer;

LoopCounter := 0;
R := FirstRecord;
while R <> nil do begin
  Inc(LoopCounter);
  if (LoopCounter >= ???) then
  begin
    LoopCounter := 0;
    Application.ProcessMessages;
  end;

  { do something simple with R.Value }
  R := R.NextRecord;
end;

أود أيضًا التصويت لصالح موضوع أو شيء من هذا القبيل Asynccalls. لحظر المستخدم على أي إجراءات غير مسموح بها خلال الوقت اللازم ، يمكنك تعيين علامة عندما يبدأ الروتين وإعادة ضبطه عند انتهائه (يجب عليك تحديث الشاشة. يمكن للموضوع الرئيسي التحقق من هذا العلامة وتعطيل جميع الإجراءات المتأثرة في حدث OnupDate الخاص بهم.

الخيار الأفضل هو نقل الحلقة إلى مؤشر ترابط العمال الخاص به بحيث لا يتم حظر الخيط الرئيسي ، فأنت لا تحتاج إلى استدعاء ProcessMessages () على الإطلاق.

ومع ذلك ، إذا كان يجب عليك القيام بالحلقة في الخيط الرئيسي ، فيمكنك استخدام msgwaitformultipleobject () للكشف عن وقت استدعاء ProcessMessages () ، أي:

Screen.Cursor = crHourGlass; 
R := FirstRecord; 
while R <> nil do begin 
  { do something simple with R.Value } 
  if MsgWaitForMultipleObjects(0, nil, False, 0, QS_ALLINPUT) = WAIT_OBJECT_0 then
    Application.ProcessMessages;
  R := R.NextRecord; 
end; 
Screen.Cursor := crDefault; 

بدلاً من ذلك مع Peekmessage ():

var Msg: TMsg;

Screen.Cursor = crHourGlass; 
R := FirstRecord; 
while R <> nil do begin 
  { do something simple with R.Value } 
  if PeekMessage(Msg, 0, 0, 0, PM_NOREMOVE) then
    Application.ProcessMessages;
  R := R.NextRecord; 
end; 
Screen.Cursor := crDefault; 

بدلاً من ذلك مع getqueuestatus ():

Screen.Cursor = crHourGlass; 
R := FirstRecord; 
while R <> nil do begin 
  { do something simple with R.Value } 
  if GetQueueStatus(QS_ALLINPUT) <> 0 then
    Application.ProcessMessages;
  R := R.NextRecord; 
end; 
Screen.Cursor := crDefault; 

أحد الأسئلة التي يجب أن تقرر ما إذا كان تطبيقك يمكن أن يستمر قبل أن يكون لديك إجابة على أي حلقة تحسب. إذا لم يتمكن ذلك من ذلك ، فلا توجد نقطة كبيرة في التطبيق "استجابة". إذا كنت تحاول تحديث شريط التقدم أو شيء ما ، فيمكنك الاتصال.

إذا تمكن التطبيق من المتابعة ، على الأقل لفترة من الوقت ، فإن وضع الرمز في موضوع فكرة جيدة.

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

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