Snížení duplicitního zpracování chyb kódu v jazyce C #?

hlasů
32

Nikdy jsem nebyl úplně spokojený s tím, jak manipulaci s výjimkou prací, je tu spousta výjimek a zkuste / catch přináší na stůl (stack odvíjení, atd.), Ale zdá se, že rozbít hodně modelu OO v tomto procesu.

Každopádně, tady je problém:

Řekněme, že máte nějakou třídu, která obtéká nebo zahrnuje síťové souborové IO operace (např čtení a psaní někde na nějakém souboru v určitém konkrétním cestu UNC). Z různých důvodů nechcete, aby tyto operace IO k selhání, takže pokud zjistíte, že se jim nepodaří si je opakovat a udržet počet opakovaných pokusů, dokud se jim to podaří, nebo se dostanete časový limit. Už mám pohodlné RetryTimer třídu, které mohu vytvořit instanci a použít ke spánku aktuální vlákno mezi opakování a určit, kdy uplyne časový limit, atd.

Problém je v tom, že máte spoustu operací IO v několika metod této třídy, a je třeba, aby zabalit každý z nich v try-catch / opakování logiku.

Zde je příklad fragment kódu:

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();
    }
}

Tak, jak se vyhnout duplikaci většinu tohoto kódu pro každý soubor IO operace v celé třídě? Moje řešení bylo použít anonymní delegáta bloky a jedinou metodu ve třídě, který provedl blok delegáta předán k němu. To mi umožnilo dělat věci, jako je to v jiných metod:

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

Líbí se mi to trochu, ale ponechává hodně být požadovaný. Rád bych slyšel, jak ostatní lidé by se řešit tento druh problému.

Položena 04/08/2008 v 20:21
zdroj uživatelem
V jiných jazycích...                            


4 odpovědí

hlasů
13

Vypadá to jako skvělou příležitost, aby se podíval na Aspect orientovaného programování. Zde je dobrý článek o AOP v .NET . Hlavní myšlenkou je, že si extrahovat kříž-funkční obavy (tj Opakovat pro x hodin) do samostatné třídy a pak si opatřit libovolné metody, které je třeba změnit jejich chování tímto způsobem. Zde je návod, jak by to mohlo vypadat (s pěkným způsobem prodloužení o Int32)

[RetryFor( 10.Hours() )]
public void DeleteArchive()
{
  //.. code to just delete the archive
}
Odpovězeno 05/08/2008 v 10:43
zdroj uživatelem

hlasů
4

Jen zeptat, co si myslíte, že vaše metoda ponechává na přání? Ty by mohly nahradit anonymní delegáta s .. jmenoval? Delegát, něco podobného

    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" );
    }
Odpovězeno 04/08/2008 v 21:07
zdroj uživatelem

hlasů
2

Tady je to, co jsem udělal v poslední době. To byl pravděpodobně provedena jinde líp, ale zdá se docela čisté a opakovaně.

Mám metodu, nástroj, který vypadá takto:

    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);
    }

Pak v mé žádosti, já používám Lamda syntaxi výraz C # 's udržet pořádek:

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

To vyžaduje mou metodu a opakování až 5krát. V pátém pokusu, původní výjimka rethrown uvnitř výjimky opakování.

Odpovězeno 13/09/2010 v 03:25
zdroj uživatelem

hlasů
2

Dalo by se také použít více OO přístup:

  • Vytvořit základní třídy, který dělá zpracování chyb a volá abstraktní metodu k provedení konkrétní práce. (Vzorové metody vzor)
  • Vytvářet konkrétní třídy pro každou operaci.

To má tu výhodu, pojmenování každý typ operace, kterou vykonávají, a dává vám příkazový vzor - operace byly reprezentovány jako objekty.

Odpovězeno 07/08/2008 v 12:30
zdroj uživatelem

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more