سؤال

كنت فقط أقرأ صفحة على الأحداث على MSDN ، واجهت مقتطفًا من رمز المثال الذي يحيرني.

الرمز المعني هو:

// Make a temporary copy of the event to avoid possibility of
// a race condition if the last subscriber unsubscribes
// immediately after the null check and before the event is raised.
EventHandler<CustomEventArgs> handler = RaiseCustomEvent;

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

هل أفتقد شيئًا واضحًا هنا؟

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

المحلول

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

نصائح أخرى

انت على حق؛ إنه ينسخ المرجع.

ومع ذلك ، فإن المندوبين غير قابلين للتغيير. عند إضافة معالج إلى حدث ما ، يتم إنشاء مندوب جديد ، يجمع بين المعالج (المعالجات) الحالي مع الحقل الجديد ، ثم يتم تعيينه إلى الحقل.

لا يمكن أن يتغير مثيل المندوب الذي يشير إليه الحقل ، لذلك يتجنب حالة السباق.

إريك ليبرت غطت هذا بالفعل في مفصل للغاية بريد.

هذا من MSDN أيضا ..

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

if (whatever != null) whatever(); يبدو أنه يضمن ذلك whatever لا يخلو أبدًا متى whatever() يسمى ، لكنه لا يضمن في الواقع أنه في سيناريو الخيوط. يمكن تعيين موضوع مختلف whatever = null بين الشيك والمكالمة.

Foo temp = whatever;
if (temp != null) temp();

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

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