2009-06-26 12 views
0

Ich verwende einen XML-Webdienst in meiner Webanwendung, und manchmal antwortet der Remoteserver nicht rechtzeitig. Ich kam auf die Idee einer erneuten Anfrage, wenn der erste Versuch fehlschlägt. Um eine Schleife zu vermeiden, möchte ich die gleichzeitige Anfrage auf 2 beschränken. Ich möchte eine Meinung erhalten, wenn das, was ich unten getan habe, in Ordnung ist und funktionieren würde, wie ich es erwarte.Wiederholen Sie die Anforderung, wenn die erste fehlgeschlagen ist

public class ScEngine 
{ 
    private int _attemptcount = 0; 
    public int attemptcount 
    { 
     get 
     { 
      return _attemptcount; 
     } 
     set 
     { 
      _attemptcount = value; 
     } 
    } 

    public DataSet GetStat(string q, string job) 
    { 

     try 
     { 
      //snip.... 
      attemptcount += attemptcount; 
      return ds; 

     } 
     catch 
     { 
      if (attemptcount>=2) 
      { 
      return null; 
      } 
      else 
      { 
       return GetStat(q, job); 
      } 

     } 

    } 
} 
+1

Seien Sie sehr, sehr vorsichtig mit diesem Ansatz; Es nistet nicht gut. Angenommen, Sie haben eine Low-Level-Methode, die einen Vorgang fünf Mal wiederholt, bevor er aufgibt. Der Anrufer versucht es fünf Mal, bevor er aufgibt. Und sein Anrufer versucht es fünf Mal, bevor er aufgibt. Plötzlich wiederholst du tatsächlich 125, bevor du aufgibst. Wir hatten reale Situationen, in denen Code, der einen Fehlercode in weniger als einer Sekunde hätte zurückgeben müssen, tatsächlich in tief verschachtelten Wiederholungen für über eine Woche saß und die Anwendung zu hängen schien. Es ist normalerweise besser, schnell zu versagen und den Benutzer entscheiden zu lassen, wann er es erneut versuchen soll. –

Antwort

1
public class ScEngine 
{ 
    public DataSet GetStat(string q, string job) 
    { 
     int attemptCount; 
     while(attemptCount < 2) 
     { 
      try 
      { 
       attemptCount++; 
       var ds = ...//web service call 
       return ds; 
      } 
      catch {} 
     } 
     //log the error 
     return null; 
    } 
} 
+1

Dies verwirft die Ausnahme (n) und protokolliert sie nie. Sehr schlecht, wenn sich herausstellt, dass die Ausnahme nicht "Timeout" oder etwas Ähnliches ist. –

+0

Sicher, Sie können die Erfassung in den Fang auch hinzufügen, wenn Sie möchten. Möglicherweise möchten Sie auch die Wiederholungsanzahl protokollieren. – RedFilter

1

Sie haben vergessen, die Anzahl der Versuche zu erhöhen. Wenn beim zweiten Durchlauf ein Fehler auftritt, wird dieser nicht abgefangen (wird also zu einer nicht behandelten Ausnahme).

+0

Auch, sollte Versuchswert sein> = 2, sonst wird es 3 Mal versuchen ... – RedFilter

+0

Eigentlich wird der Fehler auf den zweiten Lauf * gefangen werden, weil es in einem zweiten Versuch/fangen ausgeführt würde, weil er den GetStat aufruft Methode erneut. –

0

Ich würde nicht rekrutieren, um es erneut zu versuchen. Außerdem würde ich nicht alle Ausnahmen erfassen und ignorieren. Ich würde erfahren, welche Ausnahmen auf einen Fehler hinweisen, der erneut versucht werden sollte, und würde diese abfangen. Sie werden schwerwiegende Fehler ignorieren, wie Ihr Code steht.

0

Sie wollen es nicht auf diese Weise lösen. Sie werden die Server mehr belasten und mehr Timeouts verursachen.

Sie können das Zeitlimit für den Webdienst erhöhen via httpRuntime. Web-Services geben in der Regel viele Daten in einem Aufruf zurück, daher mache ich das ziemlich häufig. Vergessen Sie nicht zu erhöhen, wie lange der Client auf der Client-Seite wartet.

0

Hier ist eine Version, die keine Rekursion verwendet, aber das gleiche Ergebnis erzielt. Es enthält auch eine Verzögerung, so dass Sie dem Server Zeit geben können, um sich zu erholen, wenn es schluckt.

/// <summary> 
    /// The maximum amount of attempts to use before giving up on an update, delete or create 
    /// </summary> 
    private const int MAX_ATTEMPTS = 2; 

    /// <summary> 
    /// Attempts to execute the specified delegate with the specified arguments. 
    /// </summary> 
    /// <param name="operation">The operation to attempt.</param> 
    /// <param name="arguments">The arguments to provide to the operation.</param> 
    /// <returns>The result of the operation if there are any.</returns> 
    public static object attemptOperation(Delegate operation, params object[] arguments) 
    { 
     //attempt the operation using the default max attempts 
     return attemptOperation(MAX_ATTEMPTS, operation, arguments); 
    } 

    /// <summary> 
    /// Use for creating a random delay between retry attempts. 
    /// </summary> 
    private static Random random = new Random(); 

    /// <summary> 
    /// Attempts to execute the specified delegate with the specified arguments. 
    /// </summary> 
    /// <param name="operation">The operation to attempt.</param> 
    /// <param name="arguments">The arguments to provide to the operation.</param> 
    /// <param name="maxAttempts">The number of times to attempt the operation before giving up.</param> 
    /// <returns>The result of the operation if there are any.</returns> 
    public static object attemptOperation(int maxAttempts, Delegate operation, params object [] arguments) 
    { 
     //set our initial attempt count 
     int attemptCount = 1; 

     //set the default result 
     object result = null; 

     //we've not succeeded yet 
     bool success = false; 

     //keep trying until we get a result 
     while (success == false) 
     { 
      try 
      { 
       //attempt the operation and get the result 
       result = operation.DynamicInvoke(arguments); 
       //we succeeded if there wasn't an exception 
       success = true; 
      } 
      catch 
      { 
       //if we've got to the max attempts and still have an error, give up an rethrow it 
       if (attemptCount++ == maxAttempts) 
       { 
        //propogate the exception 
        throw; 
       } 
       else 
       { 
        //create a random delay in milliseconds 
        int randomDelayMilliseconds = random.Next(1000, 5000); 
        //sleep for the specified amount of milliseconds 
        System.Threading.Thread.Sleep(randomDelayMilliseconds); 
       } 
      } 
     } 

     //return the result 
     return result; 
    } 
Verwandte Themen