سؤال

لقد حصلت على الدرجة اسمه BackgroundWorker وقد موضوع تشغيل باستمرار.لتحويل هذا الموضوع خارج ، متغير مثيل اسمه stop أن يحتاج إلى true.

للتأكد من الخيط يتم تحرير عند الطبقة يتم استخدامها ، لقد أضفت IDisposable و finalizer التي تحتج Dispose().على افتراض أن stop = true لا بل تسبب هذا الموضوع للخروج ، هذا sippet الصحيح ؟ لا بأس أن تحتج Dispose من finalizer, صحيح ؟

Finalizers أن ندعو دائما Dispose إذا كان object يرث IDisposable, صحيح ؟

/// <summary>
/// Force the background thread to exit.
/// </summary>
public void Dispose()
{
    lock (this.locker)
    {
        this.stop = true;
    }
}

~BackgroundWorker()
{
    this.Dispose();
}
هل كانت مفيدة؟

المحلول

التعليمات البرمجية الخاصة بك على ما يرام ، على الرغم من أن تأمين في finalizer إلى حد ما "مخيفة" وأود أن تجنب ذلك - إذا كنت تحصل على الجمود...أنا لست 100 ٪ على يقين بما سيحدث لكنها لن تكون جيدة.ومع ذلك ، إذا كنت آمنة هذا لا ينبغي أن يكون مشكلة.في الغالب.الداخلية من جمع القمامة هي مؤلمة و اتمنى ان لا ترى ;)

كما مارك Gravell ، المتقلبة منطقي من شأنها أن تسمح لك للتخلص من القفل ، التي من شأنها التخفيف من حدة هذه المشكلة.تنفيذ هذا التغيير إذا كنت تستطيع.

nedruod قانون يضع مهمة داخل if (التخلص) الاختيار الذي هو خاطئ تماما - الخيط غير المدارة الموارد و يجب أن يتوقف حتى لو لم يكن صراحة التصرف.التعليمات البرمجية الخاصة بك على ما يرام, أنا فقط أشير إلى أنه يجب أن لا تأخذ النصيحة في هذا مقتطف الشفرة.

نعم, كنت دائما تقريبا يجب استدعاء Dispose() من finalizer إذا كان تنفيذ IDisposable نمط.كامل IDisposable النمط هو أكبر قليلا من ما لديك لكنك لا تحتاج دائما انها مجرد توفر اثنين من الإمكانيات الإضافية:

  1. الكشف عن ما إذا كان التصرف() كان يسمى أو finalizer تنفيذ (لا يسمح لك أن تلمس أي الموارد المدارة في finalizer خارج الكائن الذي يتم وضع اللمسات الأخيرة);
  2. تمكين الفئات الفرعية إلى تجاوز طريقة Dispose ().

نصائح أخرى

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

public void Dispose()
{
    Dispose(true);
    GC.SuppressFinalize(this);
}

/// <summary>
/// Force the background thread to exit.
/// </summary>
protected virtual void Dispose(bool disposing)
{
    if (disposing)
    {
        lock (this.locker)
        {
            this.stop = true;
        }
    }
}

~BackgroundWorker()
{
    Dispose(false);
}

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

من مصلحة أي سبب لا يمكن استخدام العادية BackgroundWorker, الذي لديه الدعم الكامل من أجل الإلغاء ؟

إعادة قفل متقلبة منطقي المجال قد تكون أقل اضطرابا.

ومع ذلك ، في هذه الحالة الخاص بك finalizer لا تفعل أي شيء مثير للاهتمام ، خصوصا "إذا كان(التخلص)" - أيفإنه يعمل فقط مثيرة للاهتمام رمز خلال التصرف().شخصيا كنت تميل إلى عصا فقط مع IDisposable ، وعدم توفر finalizer:يجب أن يكون تنظيفه مع التصرف().

هو "وقف" على سبيل المثال متغير العقار ؟ إذا لم يكن هناك أي نقطة في الإعداد أثناء finalizer - لا شيء هو الرجوع إلى كائن بعد الآن, لذلك لا شيء يمكن الاستعلام الأعضاء.

إذا كنت فعلا الإفراج عن الموارد ، ثم بعد أن تخلص() و finalizer أداء نفس العمل (أول اختبار ما إذا كان العمل لا يزال يتعين القيام به) هو نمط جيد.

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

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

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