8
votes

Répéter une fonction en C # jusqu'à ce qu'il ne jette plus une exception

J'ai une classe qui appelle une interface SOAP et obtient un tableau de données. Toutefois, si cette demande est terminée, cela jette une exception. C'est bon. Cependant, je veux que mon programme tente de rendre cet appel à nouveau. Si cela tente, j'aimerais que cela continue à faire cet appel jusqu'à ce qu'il réussisse. Comment puis-je accomplir cela?

Par exemple: P>

try
{
   salesOrdersArray = MagServ.salesOrderList(sessID, filter);
}
catch
{
   ?? What Goes Here to FORCE the above line of code to rerun until it succeeds.
}


3 commentaires

Augmenter le délai d'attente afin que cela ne jette pas l'exception?


Vous pouvez simplement appeler la méthode à nouveau à partir du bloc de capture, mais - que se passe-t-il si le service est en panne pendant une période prolongée? Voulez-vous que la méthode fonctionne de manière récursive pendant 24 heures? Je recommanderais de le limiter à un nombre défini de tentatives.


Sur toutes ces réponses, une personne ne vous dit pas d'attraper une exception plus précise. Et si votre bloc d'essai contient des objets dans un état non valide pour obtenir le salopeOrderList ? Réessayer ne réussira jamais.


11 Réponses :


4
votes

Si vous ne pouvez pas changer le délai d'attente, il faut fonctionner ci-dessous. salutordersarray doit être initialisé à null code>.

while(salesOrdersArray == null)
{
    try
    {
       salesOrdersArray = MagServ.salesOrderList(sessID, filter);
    }
    catch
    {
       // Log failure
    }
}


1 commentaires

+1: J'aime ça un peu mieux que la réponse de Jon. Je pense que cela rend la condition finale de la boucle plus évidente.



2
votes

Ce n'est généralement pas une bonne idée d'utiliser des exceptions comme flux de contrôle, mais cela fera ce que vous avez demandé. xxx


0 commentaires

0
votes
bool repeat = true;
while (repeat)
{
    try
    {
       salesOrdersArray = MagServ.salesOrderList(sessID, filter);
       repeat = false;
    }
    catch
    {
    }
}

0 commentaires

17
votes

Vous avez juste besoin de boucle pour toujours: xxx

Notez que vous devriez presque certainement pas réellement en boucle pour toujours. Vous devriez certainement certainement avoir un nombre maximum de tentatives et probablement seulement attraper des exceptions spécifiques. Attraper tous exceptions pour toujours pourrait être épouvantable ... imaginez si saléServette (nom de la méthode non conventionnelle, BTW) lance argumentnullexception Parce que vous avez un bogue et filtre est null ... Est-ce que vous vraiment veux attacher 100% de votre CPU pour toujours?


7 commentaires

Cela ne pouvait-il pas (potentiellement) attacher des ressources système et / ou rendre l'application appelante ne répondant-t-elle? Ne sonne pas comme la meilleure solution pour moi ...


@Tim: J'ajoutais le paragraphe ci-dessous - fondamentalement, le code répond directement à la question, mais le paragraphe explique que ce n'est probablement pas une bonne idée :)


+1 Pour des exceptions spécifiques, je tapais mon commentaire sur la question pendant votre édition.


Je sais que je sais que des exceptions spécifiques, des erreurs de savon, etc. Vous avez oublié les joies de la pause, merci.


@PSYKLOPZ: Vous spécifiez le type d'exception dans le bloc Catch: Catch (SoapException) etc. Vous pouvez spécifier plusieurs types d'exception différents dans plusieurs blocs de capture.


Lorsque je fais ce genre de chose, j'ai mis dans un dormir de la durée appropriée de sorte qu'il n'utilise pas 100% de la CPU en attente de service de service pour revenir en ligne. Je pourrais même inclure une brachette exponentielle limitée (comme TCP) afin qu'elle récupère rapidement des problèmes de réseau mineurs mais essaie une fois toutes les quelques minutes si le service est en panne pendant une période prolongée.


Vous pouvez également obtenir l'heure actuelle avant, puis attendez que le diff b / w puis et maintenant est> 5 sec, puis rompez (ou bien que vous voulez)



0
votes

ESSAYEZ

bool failed = false;
do {
 try
 {
  salesOrdersArray = MagServ.salesOrderList(sessID, filter);
 }
 catch
 {
  failed = true;
 }
} while(failed);


0 commentaires

0
votes

Essayez quelque chose comme ceci:

var failed = true;
while (failed)
{
  try 
  {
    salesOrdersArray = MagServ.salesOrderList(sessID, filter); 
    failed = false;
  }
  catch
  {
  }
}


0 commentaires

0
votes

Bien que je ne vous recommandais pas de le faire pour un nombre infini de fois, vous pouvez faire une fonction distincte de cette phrase:

void GoConnect()
{
    try
    {
        salesOrdersArray = MagServ.salesOrderList(sessID, filter);
    }
    catch
    {
        GoConnect();
    }
}


0 commentaires

0
votes
while(salesOrdersArray == null){

  try
  {
    salesOrdersArray = MagServ.salesOrderList(sessID, filter);
  }
  catch(salesOrderException e)
  {
     log(e.message);
  }
}
This will run forever, and is using exceptions as a loop which is slow.  Is there a way you can modify your function that it returns null, instead of throwing an exception? If you're expecting that this call will fail regularly, don't use a try/catch block.

0 commentaires

0
votes

Je suis ce modèle afin de résoudre ce problème:

    public void Send(String data, Int32 attemptNumber)
    {
        try
        {
            yourCodeHere(data);
        }
        catch (WebException ex)
        {
            if (attemptNumber > 0)
                Send(data, --attemptNumber);
            else
                throw new AttemptNumberExceededException("Attempt number exceeded!", ex);
        }
        catch (Exception ex)
        {
            //Log pourpose code goes here!
            throw;
        }
    }


6 commentaires

Pourquoi ne devrait-je pas? Mon point est le même que Jon Skeet, au-dessous du code qu'il a écrit


Ne jette ex; Stackoverflow.com/questions/178456/... Stackoverflow.com/questions/22623/...


Merci @asawyer ne savait pas à ce sujet, alors j'ai édité ma réponse! Est-ce que ça va maintenant?


Deux choses: 1- Vous ne voulez presque jamais attraper la classe d'exception de base, et si vous le faites, c'est à peu près seulement à des fins de journalisation, puis lancer à nouveau. 2 - Ne jetez jamais la base exception classe. Vous forcez de consommer du code dans la mauvaise pratique de la capture d'exception . Utilisez une sous-classe plus appropriée ou créez le vôtre.


Ça fait un vrai sens ...! Vous n'avez jamais pensé de cette façon ... Désolé de vous ennuyer, qu'en est-il de maintenant?


Il suffit de prendre un peu de temps pour lire les meilleures pratiques et vous serez en affaires en un rien de temps. Heres Quelques bons liens: blogs.msdn. COM / B / ERICLIPPERT / Archive / 2008/09/10 / ... CodeProject .com / kb / architecture / excepteBestpractices.aspx



4
votes

Vous devez placer le bloc Essayer / Catch à l'intérieur d'une construction de boucle. Si vous souhaitez ne pas consommer à 100% de votre processeur, placez un thread.sleep dans le bloc de capture, chaque fois que chaque fois une exception survient, elle attendra du temps, libérant le processeur pour faire d'autres choses.

// iterate 100 times... not forever!
for (int i = 0; i < 100; i++)
{
    try {
        // do your work here;

        break; // break the loop if everything is fine
    } catch (TimeOutException) {
        Thread.Sleep(1000);
    }
}


0 commentaires

1
votes

J'utiliserai une queue transactionnelle (MSMQ) pour stocker l'appel de service. Une boucle va ressentir des messages et appelera le service dans un transaction de transaction, si l'appel échoue, le message semble être toujours dans la file d'attente. Un délai d'attente OV Erall peut être spécifié en ajoutant un temps à expirer dans le message. Cette solution est bonne si vous voulez vraiment une solution fiable puisque j'ai deviné que l'appelant que l'opération est critique.


0 commentaires