Frage

Ich habe nie ganz glücklich mit der Art, wie die Ausnahmebehandlung funktioniert, gibt es eine Menge Ausnahmen und try/catch bringt auf den Tisch (stack unwinding, etc.), aber es scheint zu brechen viel von der OO-Modell in den Prozess.

Wie auch immer, hier ist das problem:

Lassen Sie uns sagen, dass du eine Klasse, die wraps oder schließt vernetzte Datei-E / a-Operationen (z.B.Lesen und schreiben in eine Datei in einige bestimmte UNC-Pfad irgendwo).Aus verschiedenen Gründen, die Sie nicht möchten, dass diese E / a-Vorgänge fehlschlagen, wenn Sie also erkennen, dass Sie fehlschlagen, wiederholen Sie Sie und halten Sie, wiederholen Sie, bis Sie erfolgreich sind, oder Sie erreichen einen timeout.Ich habe bereits eine günstige RetryTimer Klasse, die ich instanziieren und zu verwenden, um den Schlaf der aktuelle thread zwischen den Wiederholungen und bestimmen, wenn der timeout-Zeitraum abgelaufen, etc.

Das problem ist, dass Sie haben eine Reihe von E / a-Operationen, die in mehreren Methoden dieser Klasse, und Sie müssen, wickeln Sie jeden von Ihnen in try-catch - - / retry-Logik.

Hier ist ein Beispiel-code-snippet:

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

Also, wie vermeiden Sie das duplizieren die meisten dieser code für jede Datei-E / a-operation in der gesamten Klasse?Meine Lösung war der Einsatz von anonymen Delegaten-Blöcke und eine einzelne Methode in der Klasse, die ausgeführt wurde, wird die delegate-block übergeben.Dies ermöglichte es mir, Dinge zu tun, wie dies bei anderen Methoden:

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

Ich mag dieses etwas, aber es lässt viel zu wünschen übrig.Ich würde gerne hören, wie andere Leute würden lösen diese Art von problem.

War es hilfreich?

Lösung

Dies sieht aus wie eine hervorragende Gelegenheit, um einen Blick auf Aspekt-Orientierten Programmierung.Hier ist ein guter Artikel auf AOP in .NET.Die Allgemeine Idee ist, dass, würde man extrahieren Sie die cross-funktionale Anliegen (D. H.Wiederholen für x Stunden) in eine separate Klasse und dann würde man anmerken alle Methoden, die Notwendigkeit zu ändern Ihr Verhalten auf diese Weise.Hier ist, wie es Aussehen könnte (mit einer netten Erweiterung Methode Int32)

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

Andere Tipps

Nur Frage mich, was tun Sie fühlen sich Ihre Methode lässt zu wünschen übrig?Sie könnte ersetzen die anonymen Delegaten mit einem..Namen?delegieren, so etwas wie

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

Sie können auch eine weitere OO-Ansatz:

  • Erstellen Sie eine Basisklasse, die die Fehlerbehandlung und fordert eine abstrakte Methode zur Durchführung der konkreten Arbeit.(Template Method pattern)
  • Konkrete Klassen für jeden Betrieb.

Dies hat den Vorteil, benennt jede Art von operation, die Sie ausführen, und gibt Ihnen einen Befehl Muster - Operationen wurden als Objekte dargestellt.

Hier ist, was ich vor kurzem machte.Es wurde wahrscheinlich gemacht, die anderswo besser, aber es scheint ziemlich sauber und wiederverwendbare.

Ich habe eine utility-Methode, die wie folgt aussieht:

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

Dann in meiner Anwendung verwende ich c#'s Lamda-Ausdruck-syntax, um Ordnung zu halten:

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

Dies ruft meine Methode und wiederholt bis zu 5-mal.Bei dem fünften Versuch, die ursprüngliche Ausnahme erneut ausgelöst, ist innen eine Wiederholung Ausnahme.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top