والحد من تكرار معالجة الأخطاء البرمجية في C# ؟

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

  •  08-06-2019
  •  | 
  •  

سؤال

لم أكن سعيدا تماما مع طريقة معالجة الاستثناء يعمل هناك الكثير من الاستثناءات و حاول/catch يجلب الى طاولة المفاوضات (كومة الفك ، الخ) ، ولكن يبدو أن كسر الكثير من OO نموذج في هذه العملية.

على أي حال, هنا المشكلة:

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

المشكلة هي أن لديك مجموعة من IO عمليات في عدة طرق من هذه الفئة ، و تحتاج إلى التفاف كل واحد منهم في المحاولة-catch / إعادة المحاولة المنطق.

هنا مثال التعليمات البرمجية المتكررة:

RetryTimer fileIORetryTimer = new RetryTimer(TimeSpan.FromHours(10));
bool success = false;
while (!success)
{
    try
    {
        // do some file IO which may succeed or fail
        success = true;
    }
    catch (IOException e)
    {
        if (fileIORetryTimer.HasExceededRetryTimeout)
        {
            throw e;
        }
        fileIORetryTimer.SleepUntilNextRetry();
    }
}

هكذا, كيف يمكنك تجنب تكرار أكثر من هذا القانون لكل ملف IO العملية طوال الفصل ؟ الحل هو استخدام مجهول مندوب كتل أسلوب واحد في الصف الذي أعدم مندوب كتلة تمريرها إليه.هذا يسمح لي أن تفعل أشياء مثل هذه في طرق أخرى:

this.RetryFileIO( delegate()
    {
        // some code block
    } );

أنا أحب هذا إلى حد ما ، لكنه يترك الكثير مما هو مرغوب فيه.أود أن أسمع من الناس كيف سيكون حل هذا النوع من المشاكل.

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

المحلول

هذا يبدو وكأنه فرصة ممتازة لإلقاء نظرة على الجانب برمجة.هنا هو مادة جيدة على اوب في .صافي.الفكرة العامة هي أنك استخراج عبر وظيفية القلق (أيأعد المحاولة x ساعة) في فئة منفصلة ومن ثم علق أي من الطرق التي تحتاج إلى تعديل سلوكهم في هذا الطريق.هنا كيف قد تبدو (مع امتداد لطيفة الأسلوب على Int32)

[RetryFor( 10.Hours() )]
public void DeleteArchive()
{
  //.. code to just delete the archive
}

نصائح أخرى

أتساءل فقط ما هو شعورك الأسلوب الخاص بك من أوراق المنشود ؟ هل يمكن أن تحل محل مجهول مندوب مع..اسمه?مندوب ، شيء من هذا القبيل

    public delegate void IoOperation(params string[] parameters);

    public void FileDeleteOperation(params string[] fileName)
    {
        File.Delete(fileName[0]);
    }

    public void FileCopyOperation(params string[] fileNames)
    {
        File.Copy(fileNames[0], fileNames[1]);
    }

    public void RetryFileIO(IoOperation operation, params string[] parameters)
    {
        RetryTimer fileIORetryTimer = new RetryTimer(TimeSpan.FromHours(10));
        bool success = false;
        while (!success)
        {
            try
            {
                operation(parameters);
                success = true;
            }
            catch (IOException e)
            {
                if (fileIORetryTimer.HasExceededRetryTimeout)
                {
                    throw;
                }
                fileIORetryTimer.SleepUntilNextRetry();
            }
        }
    }

    public void Foo()
    {
        this.RetryFileIO(FileDeleteOperation, "L:\file.to.delete" );
        this.RetryFileIO(FileCopyOperation, "L:\file.to.copy.source", "L:\file.to.copy.destination" );
    }

يمكنك أيضا استخدام أكثر OO النهج:

  • إنشاء قاعدة الطبقة التي لا خطأ التعامل مع المكالمات طريقة مجردة لأداء عمل ملموسة.(قالب نمط طريقة)
  • إنشاء فئات محددة لكل عملية.

هذا له ميزة تسمية كل نوع من عملية تنفيذ ويعطيك نمط القيادة - عمليات تمثيل الكائنات.

هنا هو ما فعلته في الآونة الأخيرة.أنه قد تم في مكان آخر أفضل ، ولكن يبدو جميلة نظيفة و قابلة لإعادة الاستخدام.

لدي فائدة الطريقة التي تبدو مثل هذا:

    public delegate void WorkMethod();

    static public void DoAndRetry(WorkMethod wm, int maxRetries)
    {
        int curRetries = 0;
        do
        {
            try
            {
                wm.Invoke();
                return;
            }
            catch (Exception e)
            {
                curRetries++;
                if (curRetries > maxRetries)
                {
                    throw new Exception("Maximum retries reached", e);
                }
            }
        } while (true);
    }

ثم في طلبي, يمكنني استخدام c#'s Lamda التعبير اللغوي إلى إبقاء الأمور مرتبة:

Utility.DoAndRetry( () => ie.GoTo(url), 5);

هذا يدعو لي طريقة و المحاولات تصل إلى 5 مرات.في المحاولة الخامسة ، الأصلي استثناء rethrown داخل المحاولة استثناء.

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