سؤال

هناك موضوع في دلفي التطبيق الذي لديه رسالة-في انتظار الحلقة.في كل مرة يتلقى رسالة ، ويبدأ في القيام ببعض الأعمال.هنا هو تنفيذ الإجراء من هذا الموضوع:

procedure TMyThread.Execute;
begin
  while GetMessage(Msg, 0, 0, 0) and not Terminated do
  begin
    {thread message}
    if Msg.hwnd = 0 then
    begin
      ...
    end
    else
      DispatchMessage(Msg);
  end;
end;

القيام ببعض الاختبارات باستخدام تطبيق اكتشفت أن الدالة GetMessage هو الترابط الرئيسي تعتمد.هذا يعني أنه في حين أن الموضوع الرئيسي هو القيام ببعض الأعمال ، GetMessage الوظيفة في موضوع لا يرجع على الرغم من رسالة ينتظر أن يتم استلامها من قبل ذلك (الرسالة المرسلة من قبل آخر الخيط باستخدام PostThreadMessage funciton:PostMessage(MyThreadId, WM_MyMessage, 0, 0)).

فقط عندما الخيط الرئيسي انتهاء العمل أو التطبيق.ProcessMessages ما يسمى طريقة لا GetMessage العودة و الخيط يبدأ القيام بعملها.تنفيذ هذا النوع من بين موضوع البلاغ كنت على يقين من أن بلدي المواضيع سوف تعمل بشكل مستقل و لن نتوقع أن استقبال الرسائل المرسلة مباشرة إلى خيط من شأنه أن تعتمد على الترابط الرئيسي.

القيام اختبارات لقد استخدمت WaitForSingleObject وظيفة في الموضوع الرئيسي, انتظار حدث لبضع ثوان.هذا هو عندما لاحظت أن موضوع بلدي لا تقوم بأي عمل حتى ولو تم إرسال رسائل إلى ذلك من قبل مؤشر ترابط آخر.عندما WaitForSingleObject وظيفة انتهى أخيرا انتظار مؤشر الترابط الرئيسي أصبح خاملا ، GetMessage وظيفة في الموضوع عاد.

هل يمكن لأحدكم أن يشرح لي لماذا يعمل هذا الطريق ؟ هل هناك حل لذلك ؟ أود أن أجعل موضوع تلقي الرسائل بشكل مستقل.جميع المواضيع التي تم إنشاؤها بواسطة الخيط الرئيسي.قد يكون هذا السبب ؟

شكرا على المساعدة مسبقا.

ماريوس.


Mghie كنت على حق تماما مرة أخرى (ساعدتني مع الرسائل الاشياء مؤخرا ، قد تذكر).كما اقترح GetMessage يعود على الفور ، ولكن الموضوع توقف ، في الواقع ، على الدعوة إلى النافذة الرئيسية طريقة:

procedure TMyThread.Execute;
begin
  while GetMessage(Msg, 0, 0, 0) and not Terminated do
  begin
    {thread message}
    if Msg.hwnd = 0 then
    begin
      ...
      if Assigned(FOnCommEventMethod) then
        FOnCommEventMethod(FCommEventsQueueItem);
      ...
    end
    else
      DispatchMessage(Msg);
  end;
end;

FOnCommEventMethod هو أسلوب كائن أعلن 'الداخلي (EventMask:الكاردينال) من وجوه;' (هذا الموضوع يعالج المنفذ التسلسلي الأحداث).في هذه الحالة FOnCommEventMethod تم تعيين الإجراء تنتمي إلى النموذج الرئيسي الدرجة.عندما الأسلوب يسمى بلدي خيط, خيط معلق في انتظار مؤشر الترابط الرئيسي لإنهاء عملها.

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

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

شكرا على مساعدتك.إذا لم تساعدني أنا ربما التخلص من الرسائل واستخدام الأحداث بدلا من ذلك ، وأخيرا أود أن تلاحظ أن ذلك لم يكن السبب :-).

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

المحلول

<اقتباس فقرة>   

وفقط عندما ينتهي موضوع الرئيسي عملها أو يتم استدعاء أسلوب Application.ProcessMessages، هل GetMessage العودة وموضوع بلدي يبدأ به عمله.

وأشك في أن هذا هو حقا ما يحدث. AFAIK الرسالة اثنين من الحلقات يجب أن تكون مستقلة عن بعضها البعض، طالما أنك لا تستخدم وسائل أخرى للمزامنة المواضيع، مثل SendMessage () . هل أنت متأكد من أن موضوع لا تمنع في الواقع داخل <م> GetMessage () وليس داخل <م> تزامن () (التي تستخدم SendMessage () داخليا )؟

<اقتباس فقرة>   

والقيام الاختبارات I استخدام الدالة WaitForSingleObject في الموضوع الرئيسي، في انتظار حدث لبضع ثوان.

ويجب أن تستخدم أبدا <م> WaitForSingleObject () في موضوع الرئيسي مع مهلة أطول من يقول 100 ميلي ثانية، حيث سيؤدي ذلك إلى جعل واجهة المستخدم الرسومية الخاصة بك تظهر تباطؤ. في الحقيقة أنصح لك عدم استخدامها على الإطلاق في موضوع الرئيسي، لأن هذا هو ببساطة الاقتراع. أضف رسالة من ترابط عامل بدلا من ذلك.

نصائح أخرى

يمكنك إنشاء رسالة انتظار مؤشر الترابط الخاص بك.فقط تنفيذ التعليمات البرمجية التالية في الموضوع:

MSG msg;
PeekMessage(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE);
SetEvent(messageQueueReady);
while (GetMessage(&msg, NULL, 0, 0)) 
{
    ...// do message processing here
}

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

تحرير: آسف على سبيل المثال يجري في ج ، ونأمل أن على ما يرام بالنسبة لك.

HTTP: // groups.google.com/group/borland.public.delphi.language.delphi.win32/browse_thread/thread/cf368834a606321b

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

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