سؤال

كتبت متعددة الخيوط تطبيق ويندوز حيث الموضوع:
A – هو نموذج windows الذي يتعامل مع تفاعل المستخدم ومعالجة البيانات من B.
ب – أحيانا يولد البيانات ويمررها اثنين A.

موضوع آمنة طابور يستخدم لتمرير البيانات من مؤشر ترابط B إلى A.على إدراج بقائمة الانتظار و dequeue مهام حراسة باستخدام ويندوز الحرجة قسم الكائنات.

إذا كانت قائمة الانتظار فارغة عند إدراج بقائمة الانتظار استدعاء الدالة استخدام PostMessage أن أقول أن هناك البيانات في قائمة الانتظار.وظيفة الشيكات للتأكد من الدعوة إلى PostMessage يتم تنفيذها بنجاح و يدعو مرارا وتكرارا PostMessage إذا لم يكن ناجحا (PostMessage لم تفشل).

هذا يعمل جيدا لبعض الوقت حتى كمبيوتر واحد معين بدأت تفقد رسالة في بعض الأحيان.خلال تفقد أعني أن PostMessage يعود بنجاح في ب ولكن لم يتلقى الرسالة.يؤدي هذا البرنامج تظهر المجمدة.

لدي بالفعل التوصل إلى عدة مقبول الحلول.أنا مثيرة للاهتمام في معرفة لماذا يقوم نظام ويندوز هو فقدان هذه الرسائل و لماذا هذا يحدث فقط على جهاز كمبيوتر واحد.

هنا هو الأجزاء ذات الصلة من القانون.

// Only called by B
procedure TSharedQueue.Enqueue(AItem: TSQItem);
var
 B: boolean;
begin
  EnterCriticalSection(FQueueLock);
  if FCount > 0 then
    begin
      FLast.FNext := AItem;
      FLast := AItem;
    end
  else
    begin
      FFirst := AItem;
      FLast := AItem;
    end;

  if (FCount = 0) or (FCount mod 10 = 0) then // just in case a message is lost
    repeat
      B := PostMessage(FConsumer, SQ_HAS_DATA, 0, 0);
      if not B then 
  Sleep(1000); // this line of code has never been reached
    until B;

  Inc(FCount);
  LeaveCriticalSection(FQueueLock);
end;

// Only called by A 
function TSharedQueue.Dequeue: TSQItem;
begin
  EnterCriticalSection(FQueueLock);
  if FCount > 0 then
    begin
      Result := FFirst;
      FFirst := FFirst.FNext;
      Result.FNext := nil;
      Dec(FCount);
    end
  else
    Result := nil;
  LeaveCriticalSection(FQueueLock);
end;

// procedure called when SQ_HAS_DATA is received
procedure TfrmMonitor.SQHasData(var AMessage: TMessage);
var
  Item: TSQItem;
begin
  while FMessageQueue.Count > 0 do
    begin
      Item := FMessageQueue.Dequeue;
      // use the Item somehow
    end;
end;
هل كانت مفيدة؟

المحلول

هو FCount كما يحميها FQueueLock?إذا المشكلة تكمن مع FCount يتم زيادة بعد نشر الرسالة المجهزة مسبقا.

هنا ما يمكن أن يحدث:

  1. ب يدخل الحرجة القسم
  2. ب المكالمات PostMessage
  3. وهو يتلقى الرسالة ولكن لا تفعل أي شيء منذ FCount هو 0
  4. ب الزيادات FCount
  5. ب يترك مقطع حرج
  6. يجلس هناك مثل البطة

سريع العلاج سيكون على الاضافة FCount قبل استدعاء PostMessage.

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

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

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

نصائح أخرى

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

إذا قائمة الانتظار فارغ عند إدراج بقائمة الانتظار   يتم استدعاء الدالة، فإن وظيفة   استخدام PostMessage أن أقول أن هناك A   هي البيانات في قائمة الانتظار.

هل تأمين قائمة انتظار الرسالة قبل التحقق من حجم الطابور وإصدار PostMessage؟ قد تكون تعاني من حالة سباق حيث قمت بالتدقيق في قوائم الانتظار وتجد أنه من غير فارغة في حين أن هناك بمعالجة الرسالة الأخيرة جدا وعلى وشك أن يذهب الخمول.

لمعرفة ما إذا كنت في الواقع تعاني من حالة تعارض وليست مشكلة مع PostMessage، هل يمكن أن التحول إلى استخدام هذا الحدث. إن ترابط العامل (A) الانتظار على الحدث بدلا من انتظار رسالة. سوف B ببساطة تعيين هذا الحدث بدلا من نشر الرسالة.

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

وهذا يعمل بشكل جيد لبعض الوقت   حتى بدأ جهاز كمبيوتر واحد محدد ل   تفقد رسالة من حين لآخر.

وقبل أي فرصة، لا عدد وحدات المعالجة المركزية أو النوى أن هذه كمبيوتر معين يكون مختلفا عن الآخرين حيث كنت لا أرى أي مشكلة؟ في بعض الأحيان عند التبديل من جهاز واحد وحدة المعالجة المركزية للجهاز مع أكثر من البدني وحدة المعالجة المركزية / الأساسية، قد تنشأ ظروف سباق جديدة أو الجمود.

ويمكن أن يكون هناك مثيل الثاني على التوالي تدري وتناول الرسائل، وسم لهم كما عالجت؟

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