[c#] متى يتم التخلص من CancellationTokenSource؟



Answers

لقد إلقاء نظرة في ILSpy من أجل CancellationTokenSource ولكن يمكنني فقط العثور على m_KernelEvent وهو في الواقع ManualResetEvent ، وهو فئة مجمّع لكائن WaitHandle. ينبغي التعامل مع هذا بشكل صحيح من قبل GC.

Question

الفئة CancellationTokenSource يمكن التخلص منها. نظرة سريعة في Reflector يثبت استخدام KernelEvent ، مورد (غير مرجح) غير مدار بشكل كبير. نظرًا لأن CancellationTokenSource لا يحتوي على أداة finalizer ، إذا لم نتخلص منها ، فلن يفعلها GC.

من ناحية أخرى ، إذا نظرت إلى النماذج المذكورة في المقالة MSDN إلغاء في "مؤشرات ترابط مدارة" ، قصاصة رمز واحد فقط يتصرف الرمز المميز.

ما هي الطريقة الصحيحة للتخلص منها في الكود؟

  1. لا يمكنك لف التعليمة البرمجية التي تبدأ مهمتك المتوازية using إذا لم تنتظرها. ومن المنطقي أن يكون الإلغاء فقط إذا لم تنتظر.
  2. بالطبع يمكنك إضافة ContinueWith في مهمة مع مكالمة Dispose ، ولكن هل هذا هو الطريق للذهاب؟
  3. ماذا عن استفسارات PLINQ الملغاة ، التي لا تتم مزامنتها مرة أخرى ، ولكن هل تفعل شيئًا في النهاية؟ دعنا نقول .ForAll(x => Console.Write(x)) ؟
  4. هل يعاد استخدامها؟ هل يمكن استخدام الرمز المميز نفسه لعدة مكالمات ، ثم التخلص منه مع مكون المضيف ، دعنا نقول عنصر واجهة المستخدم؟

لأنه ليس لديه شيء مثل أسلوب Reset لتنظيف حقل IsCancelRequested و Token ، أفترض أنه غير قابل لإعادة الاستخدام ، وبالتالي في كل مرة تقوم فيها بتشغيل مهمة (أو استعلام PLINQ) ، يجب أن تقوم بإنشاء واحدة جديدة. هل هذا صحيح؟ إذا كانت الإجابة بنعم ، سؤالي هو ما هي الإستراتيجية الصحيحة والموصى بها للتعامل مع Dispose على تلك الحالات العديدة CancellationTokenSource ؟




إنشاء تطبيق Windows Forms جديد من قالب المشروع. أفلت زرًا في النموذج وانقر عليه نقرًا مزدوجًا. اجعلها تبدو كما يلي:

    private void button1_Click(object sender, EventArgs e) {
        var t = new System.Threading.Thread(() => { });
        t.Start();
    }

اضغط على Ctrl + F5 لبدء تشغيله. بدء + تشغيل ، TaskMgr.exe ، علامة التبويب العمليات. عرض + اختيار الأعمدة ووضع علامة "مقابض". مراقبة قيمة هذا العمود لعملية WindowsFormsApplication1.exe أثناء النقر فوق الزر بشكل متكرر.

لا يحتوي فئة مؤشر الترابط أسلوب Dispose ().

دعونا نعمل من افتراض أن لديها واحدة. متى تسميها؟

اقرأ المزيد عن الحكمة من محاولة التخلص من الأشياء التي يصعب التخلص منها في reference قبل Stephen Toub.




يجب عليك دائمًا التخلص من CancellationTokenSource .

كيفية التخلص منه يعتمد بالضبط على السيناريو. تقترح عدة سيناريوهات مختلفة.

  1. using فقط يعمل عند استخدام CancellationTokenSource في بعض الأعمال المتوازية التي تنتظرها. إذا كان هذا هو senario الخاص بك ، ثم رائع ، فهو أسهل طريقة.

  2. عند استخدام المهام ، استخدم مهمة ContinueWith كما أشرت للتخلص من CancellationTokenSource .

  3. بالنسبة إلى plinq ، يمكنك استخدام الاستخدام نظرًا لأنك تقوم بتشغيله بشكل متوازٍ ، ولكن في انتظار انتهاء جميع العاملين المتوازيين.

  4. بالنسبة إلى واجهة المستخدم ، يمكنك إنشاء CancellationTokenSource جديد لكل عملية قابلة للإلغاء غير مرتبطة بمشغل إلغاء واحد. الاحتفاظ بقائمة List<IDisposable> وإضافة كل مصدر إلى القائمة ، والتخلص منها جميعًا عند التخلص من المكون الخاص بك.

  5. مؤشرات الترابط ، إنشاء مؤشر ترابط جديد يصل كافة مؤشرات ترابط worker وإغلاق مصدر واحد عند الانتهاء من كافة مؤشرات ترابط worker. انظر CancellationTokenSource ، متى يتم التصرف؟

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




Links