在C#中重复一个函数,直到它不再抛出exception

我有一个调用SOAP接口的类,并获取一个数据数组。 但是,如果此请求超时,则会引发exception。 这很好。 但是,我希望我的程序再次尝试进行此调用。 如果它超时,我希望它继续拨打这个电话,直到它成功为止。 我怎么能做到这一点?

例如:

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

你只需要永远循环:

 while (true) { try { salesOrdersArray = MagServ.salesOrderList(sessID, filter); break; // Exit the loop. Could return from the method, depending // on what it does... } catch { // Log, I suspect... } } 

请注意,您几乎肯定不会实际上永远循环。 您几乎肯定会有最大的尝试次数,并且可能只捕获特定的exception。 永远捕获所有exception可能是令人震惊的…想象一下如果salesOrderList (非常规方法名称,顺便说一句)抛出ArgumentNullException因为你有一个bug并且filter是null …你真的想永远占用100%的CPU吗?

如果您无法更改超时,则以下内容应该有效。 salesOrdersArray应初始化为null

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

您必须将try / catch块放在循环结构中。 如果你不想消耗100%的处理器,那么在catch块中放置一个Thread.Sleep,所以每次发生exception时,它都会等待一段时间,让处理器释放其他东西。

 // 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 { Thread.Sleep(1000); } } 

您还可以指定exception类型,以便仅处理超时exception,并传递其他类型的exception。

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

请注意,TimeOutException应该替换为exception的真实名称...我不知道这是否是真实姓名。

同时调整以毫秒为单位的hibernate时间和重复次数,在我提出的情况下,100次重复1000次产生最长等待1分40秒,加上操作时间本身。

使用exception作为控制流程并不是一个好的理想,但这可以满足您的要求。

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

我将使用事务性队列(MSMQ)来存储服务调用。 循环将使消息出列并在TransactionScope中调用服务,如果调用失败,则消息似乎仍在队列中。 可以通过在消息中添加到期时间来指定总体超时。 如果你真的想要一个可靠的解决方案,这个解决方案是好的,因为我猜这个操作是至关重要的。

尝试

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

你所追求的行为可能会导致无限循环,如果这永远不会成功…

尝试这样的事情:

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

编辑:哇! 英雄所见略同! 🙂

虽然我不建议你无限次地执行此操作,但你可以用一个句子创建一个单独的函数:

 void GoConnect() { try { salesOrdersArray = MagServ.salesOrderList(sessID, filter); } catch { GoConnect(); } } 
 while(salesOrdersArray == null){ try { salesOrdersArray = MagServ.salesOrderList(sessID, filter); } catch(salesOrderException e) { log(e.message); } } 

这将永远运行,并使用exception作为一个缓慢的循环。 有没有办法可以修改你的函数,它返回null,而不是抛出exception? 如果您希望此调用会定期失败,请不要使用try / catch块。

我遵循这种模式来解决这个问题:

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

永远尝试似乎不是一个好主意,因为你最终可能会有一个无限的过程。 如果您认为需要多次尝试来实现目标,请在此处设置大量数字。

我个人认为在eac尝试Thread.Sleep(1000)之后等待几毫秒或者几秒钟是明智的 在callig 发送之前(数据); —例如,如果你认为它适用于你的场景,你可以使用attemptNumber变量来增加或减少这个等待时间。

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