كيفية التعامل مع جميع الاستثناءات غير المعلنة عند استخدام المكتبة الموازية للمهمة؟

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

سؤال

أنا أستخدم TPL (المكتبة الموازية للمهمة) في .NET 4.0. أرغب في تركيز منطق المناولة لجميع الاستثناءات غير المعلنة باستخدام Thread.GetDomain().UnhandledException حدث. ومع ذلك ، في طلبي ، لم يتم إطلاق الحدث أبدًا للخيوط التي بدأت برمز TPL ، على سبيل المثال Task.Factory.StartNew(...). تم إطلاق الحدث بالفعل إذا استخدمت شيئًا مثل new Thread(threadStart).Start().

هذه المقالة MSDN يقترح استخدام Task.wait () للقبض AggregateException عند العمل مع TPL ، لكن هذا ليس ما أريده لأن هذه الآلية ليست "مركزية" بدرجة كافية.

هل يواجه أي شخص نفس المشكلة على الإطلاق أم أنه أنا فقط؟ هل لديك أي حل لهذا؟

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

المحلول 2

يبدو أنه لا توجد طريقة مدمجة للتعامل مع هذا (ولا توجد إجابة على هذا السؤال بعد ما يقرب من أسبوعين). لقد قمت بالفعل بطرح بعض التعليمات البرمجية المخصصة لرعاية هذا. وصف الحل طويل جدًا ، لذلك قمت بنشره في مدونتي. تشير إلى هذا المشنور إذا كنت مهتما.

تحديث 5/7/2010: لقد وجدت طريقة أفضل للقيام بذلك ، والاستفادة من استمرار المهام. أنا إنشاء class ThreadFactory هذا يعرض حدث الخطأ الذي يمكن الاشتراك فيه بواسطة معالج المستوى الأعلى ويوفر طرقًا لبدء مهمة متصلة باستمرار مناسب.
تم نشر الرمز هنا.

تحديث 4/18/2011: رمز النشر من منشور المدونة حسب تعليق نيفل.

internal class ThreadFactory
{
    public delegate void TaskError(Task task, Exception error);

    public static readonly ThreadFactory Instance = new ThreadFactory();

    private ThreadFactory() {}

    public event TaskError Error;

    public void InvokeError(Task task, Exception error)
    {
        TaskError handler = Error;
        if (handler != null) handler(task, error);
    }

    public void Start(Action action)
    {
        var task = new Task(action);
        Start(task);
    }

    public void Start(Action action, TaskCreationOptions options)
    {
        var task = new Task(action, options);
        Start(task);
    }

    private void Start(Task task)
    {
        task.ContinueWith(t => InvokeError(t, t.Exception.InnerException),
                            TaskContinuationOptions.OnlyOnFaulted |
                            TaskContinuationOptions.ExecuteSynchronously);
        task.Start();
    }
}

نصائح أخرى

أظن TASKSCHEDULER.UNOBSERVEDTASKEXCEPTION هو ما تريد:

يحدث عندما يكون خطأ مهام الاستثناء غير الملحوظ على وشك تشغيل سياسة تصعيد الاستثناء ، والتي ، بشكل افتراضي ، ستنهي العملية.

لذلك ، يشبه هذا الحدث DomainUnhandledException التي ذكرتها في سؤالك ولكنها تحدث فقط للمهام.

راجع للشغل ، هذه سياسة الاستثمار غير الملحوظة (نعم ، هذه ليست استثناءات غير مراقبة ، ابتكرت MS Guys كلمة جديدة ... مرة أخرى) ، تم تغييرها من .NET 4.0 إلى .NET 4.5. في .NET 4.0 الاستثناء غير الملحوظ يؤدي إلى إنهاء عملية ولكن في .NET 4.5 - لا. هذا كل شيء لأن الأشياء غير المتزامنة الجديدة التي سنحصل عليها في C# 5 و VB 11.

أرى خيارين يمكن استخدامهما لأغراض مركزية معالجة الاستثناء في TPL: 1. استخدام حدث استثناء المهام غير المرصود. 2. استخدام الاستمرارية للمهام مع الحالة المعطلة.

استخدام حدث استثناء المهام غير الملحوظ من جدولة المهام.

يحتوي جدولة المهام على حدث غير مراقب kexkexception الذي يمكنك الاشتراك فيه باستخدام المشغل +=.

  • الملاحظة 1: في مجموعة المعالج ، تحتاج إلى جعل SetObserved () على حجة غير مراقبة kexcepectioneventargs لإخطار جدولة أنه تم التعامل مع الاستثناء.
  • ملاحظة 2: يتم استدعاء المعالج عندما يتم جمع المهام من قبل جامع القمامة.
  • الملاحظة 3: إذا كنت ستنتظر المهمة ، فستظل مضطرًا لحماية الانتظار عن طريق التجربة.
  • الملاحظة 4: السياسة الافتراضية لاستثناءات المهمة غير المعروفة في .NET 4.0 و 4.5 مختلفة.

ملخص: هذا النهج جيد لمهام النار والناشئة وللتقاط استثناءات هربت من سياسة معالجة الاستثناءات المركزية الخاصة بك.

استخدام الاستمرارية للمهام مع الحالة المعطلة.

باستخدام TPL ، يمكنك إرفاق الإجراءات بالمهمة باستخدام Method Continuewith () والتي تأخذ خيار الإجراء والاستمرار. سيتم استدعاء هذا الإجراء بعد إنهاء المهمة وفقط في الحالات المحددة حسب الخيار. خاصه:

    t.ContinueWith(c => { /* exception handling code */ },
                   TaskContinuationOptions.OnlyOnFaulted);

يقوم بتثبيت استمرار مع استثناء رمز التعامل مع المهمة ر. سيتم تشغيل هذا الرمز فقط في الحالة التي تم فيها إنهاء المهمة T بسبب الاستثناء غير المعدل.

  • ملاحظة 1: احصل على قيمة استثناء في رمز معالجة الاستثناء. وإلا فإنه سيتم الخروج.
  • ملاحظة 2: سيتم استدعاء رمز معالجة الاستثناء مباشرة بعد إنهاء المهمة.
  • ملاحظة 3: إذا تم الحصول على استثناء من رمز معالجة الاستثناء ، فسيتم اعتباره معالجته ، فلن يتمكن Try/Catch في انتظار المهمة من التقاطه.

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

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