مشكلة تعدد مؤشرات الترابط في C# مع فئة المراقبة - احتمالية قفل الحياة؟

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

سؤال

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

lock (lockObject)
{
   if (!Monitor.TryEnter(lockObject))
     Monitor.Wait(lockObject);

   //do stuff...
   Monitor.PulseAll(lockObject);
}
Monitor.Exit(lockObject);

المشكلة التي أواجهها هي أنه في وقت ما تبدو جميع المواضيع نائمة - هل يمكن لأحد أن يقول لماذا؟يستمر البرنامج في العمل إلى ما لا نهاية ولا يستهلك أي وحدة معالجة مركزية تقريبًا ولكن لا يتم القيام بأي عمل - عند تتبع البرنامج، اكتشفت أنه في مرحلة ما لا يوجد مؤشر ترابط نشط ولكن الكثير منهم في وضع السكون.أعلم أن الخطأ يقع في الغالب (في حالة المطور - دائمًا) على بعد 0.5 متر أمام الشاشة - لكن لا يمكنني اكتشاف ذلك بنفسي...ربما في بضع دقائق ;)

هل يمكن لأحد أن يشرح لي ذلك - شكرًا مقدمًا.

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

المحلول

هل هناك فرق بين LockObject و lockObject؟ليس واضحا...

لكن!إذا كانت كائنات مختلفة، أولاً:لا يمكنك Wait على القفل الذي ليس لديك...و TryEnter سيُرجع خطأ فقط إذا حددت مهلة.ما الذي يحاول هذا الرمز فعله بالضبط؟

بدون مزيد من السياق، ليس من الواضح تمامًا ما هو PulseAll و Wait مصممة للقيام بها؛على سبيل المثال، هنا يتم استخدامها لحظر قائمة الانتظار عندما تكون ممتلئة جدًا (Wait)، أو قم بتحريره عندما تتوفر مساحة (PulseAll)، إلخ.من الصعب تصحيح أخطاء كود الترابط دون التفاعلات الكاملة بين سلاسل الرسائل.

يبدو أنك قد تحتاج فقط إلى:

lock (lockObject)
{
    // do stuff
}

هناك مشكلتان مباشرتان أستطيع رؤيتهما؛أولاً، ليس من الواضح أنك تقوم دائمًا بتحرير الأقفال التي تأخذها (أي.الاستثناءات).حاول أن تستخدم فقط lock ل Enter/Exit - سوف تحصل على حق.

ثانية؛إذا كانت جميع المواضيع الدعوة Wait...من سيوقظهم؟ماذا ينتظرون ل؟كما قدمت:نعم، سوف ينامون جميعا إلى أجل غير مسمى.

نصائح أخرى

وأنا assming البيان القفل الأول هو الخطأ المطبعي وكنت تعني القفل (lockObject) (صغيرة).

وأعتقد أنك سوء فهم أقفال قليلا هنا. سوف إذا كتلة في التعليمات البرمجية الخاصة بك لن تكون أبدا صحيح. السبب هو أن القفل (lockObject) exapands فعلا لما يلي

Monitor.Enter(lockObject);
try {
...
} finally{ 
Monitor.Exit(lockObject);

وهكذا في الوقت الذي ضرب إذا كتلة كنت تملك بالفعل القفل وTryEnter يجب أن تنجح دائما.

وهذا هو الإعداد غريب. هو 'LockObject' نفس 'lockObject؟ أم أن ذلك خطأ مطبعي؟ إذا كانت هي نفسها، ثم الإعداد لا لزوم لها، وليس هناك حاجة لاستدعاء Monitor.TryEnter على شيء كنت قفل بالفعل. إذا "LockObject" هو كائن مختلف، ثم لماذا لا نقل Monitor.Exit إلى داخل بيان قفل؟

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