سؤال

لقد كتبت مكون com في .NET وإذا حاولت قفل أي كائن بأي طريقة (يتم استدعاؤه بواسطة تعليمات برمجية غير مُدارة تتحدث إلى مكون com الخاص بي) أحصل على استثناء.

ليس لدي النص الدقيق للاستثناء في هذه اللحظة ولكنه لم يكن مفيدًا أيضًا.

لذا فإن سؤالي هو تحت أي ظروف قد يقوم القفل (syncObject) بإلقاء استثناء؟وهنا بعض الحقائق:

  • كائن المزامنة ليس فارغًا
  • لم يتم تأمين syncObject بالفعل

هل سيكون لها أي علاقة بتشغيل المستدعي في STA (شقة مفردة مترابطة) أو MTA (شقة متعددة الخيوط)؟

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

المحلول

من هذه الصفحة:

كل عملية شراء للقفل قد تؤدي إلى استثناء.كن مستعدا لذلك.

تقوم معظم الأقفال بتخصيص حدث بتكاسل إذا واجه الحصول على القفل تنافسًا، بما في ذلك شاشات CLR.يمكن أن يفشل هذا التخصيص أثناء ظروف انخفاض الموارد، مما يتسبب في ظهور OOMs من المدخل إلى القفل.(لاحظ أن قفل الدوران النموذجي غير المحظور لا يمكن أن يفشل مع OOM، مما يسمح باستخدامه في بعض السيناريوهات المحدودة الموارد مثل داخل CER.) وبالمثل، يمكن لمضيف مثل SQL Server إجراء الكشف عن حالة توقف تام وحتى كسر تلك حالة توقف تام عن طريق إنشاء الاستثناءات التي تنشأ من عبارة Enter، والتي تظهر كـ System.Runtime.InteropServices.COMException.

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

لذا، كما يمكنك أن تقرأ، يبدو أنه في ظل الظروف المحدودة للموارد قد نحصل على استثناءات من طريقة Enter للمراقبة التي يستخدمها lock(o) داخليًا.

لذا ربما يكون الحل الخاص بك هو شيء يشبه الانتظار؟

{
    uint iters = 0;
    while (!cond) {
        if ((++iters % 50) == 0) {
            // Every so often we sleep with a 1ms timeout (see #30 for justification).
            Thread.Sleep(1);
        } else if (Environment.ProcessorCount == 1) {
            // On a single-CPU machine we yield the thread.
            Thread.Sleep(0);
        } else {
            // Issue YIELD instructions to let the other hardware thread move.
            Thread.SpinWait(25);
        }
    }
}

حيث يمكن أن يكون بعض

private volatile int cond = 0

تستخدم مع على سبيل المثالInterlocked.CompareExchange حيث يمكنك التغيير إلى على سبيل المثال.Thread.Current.ManagedThreadID أو أي شيء آخر غير الصفر؟

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