我有一个调用SOAP接口的类,并获取一个数据数组。但是,如果此请求超时,则会引发异常。这很好。但是,我希望我的程序再次尝试进行此调用。如果它超时,我希望继续拨打这个电话,直到它成功为止。我怎么能做到这一点?
例如:
try
{
salesOrdersArray = MagServ.salesOrderList(sessID, filter);
}
catch
{
?? What Goes Here to FORCE the above line of code to rerun until it succeeds.
}
答案 0 :(得分:16)
你只需要永远循环:
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...
}
}
请注意,您几乎肯定不实际上永远循环。您几乎肯定会有最大尝试次数,并且可能只捕获特定的异常。抓住所有异常永远可能会令人震惊......想象如果salesOrderList
(非常规方法名称,btw)抛出ArgumentNullException
因为你有一个错误和filter
为空...你真的想永远占用100%的CPU吗?
答案 1 :(得分:4)
如果您无法更改超时,则以下情况应该有效。 salesOrdersArray应初始化为null
。
while(salesOrdersArray == null)
{
try
{
salesOrdersArray = MagServ.salesOrderList(sessID, filter);
}
catch
{
// Log failure
}
}
答案 2 :(得分:2)
使用异常作为控制流通常不是一个好主意,但这将按照您的要求执行。
bool Caught = true;
while (Caught)
try
{
salesOrdersArray = MagServ.salesOrderList(sessID, filter);
Caught = false;
}
catch
{
Caught = true;
}
答案 3 :(得分:2)
您必须将try / catch块放在循环结构中。如果你不想消耗100%的处理器,那么在catch块中放置一个Thread.Sleep,所以每次发生异常时,它都会等待一段时间,让处理器自由地做其他事情。
// 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);
}
}
您还可以指定异常类型,以便仅处理超时异常,并传递其他类型的异常。
// 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应替换为异常的真实名称...我不知道这是否是真实姓名。
同样调整睡眠时间,以毫秒为单位给出,重复次数,在我呈现的情况下,100次重复1000ms产生最长等待1分40秒,加上操作时间本身。
答案 4 :(得分:1)
我将使用事务性队列(MSMQ)来存储服务调用。循环将使消息出列并在TransactionScope中调用服务,如果调用失败,则消息似乎仍在队列中。可以通过在消息中添加到期时间来指定总体超时。如果你真的想要一个可靠的解决方案,这个解决方案是好的,因为我猜这个操作是至关重要的。
答案 5 :(得分:0)
bool repeat = true;
while (repeat)
{
try
{
salesOrdersArray = MagServ.salesOrderList(sessID, filter);
repeat = false;
}
catch
{
}
}
答案 6 :(得分:0)
尝试
bool failed = false;
do {
try
{
salesOrdersArray = MagServ.salesOrderList(sessID, filter);
}
catch
{
failed = true;
}
} while(failed);
如果从未成功过,那么你所追求的行为可能会导致无限循环......
答案 7 :(得分:0)
尝试这样的事情:
var failed = true;
while (failed)
{
try
{
salesOrdersArray = MagServ.salesOrderList(sessID, filter);
failed = false;
}
catch
{
}
}
编辑:哇!英雄所见略同! :)
答案 8 :(得分:0)
虽然我不建议你无数次这样做,但你可以用这句话单独编写一个函数:
void GoConnect()
{
try
{
salesOrdersArray = MagServ.salesOrderList(sessID, filter);
}
catch
{
GoConnect();
}
}
答案 9 :(得分:0)
while(salesOrdersArray == null){
try
{
salesOrdersArray = MagServ.salesOrderList(sessID, filter);
}
catch(salesOrderException e)
{
log(e.message);
}
}
这将永远运行,并且使用异常作为一个缓慢的循环。有没有办法可以修改你的函数,它返回null,而不是抛出异常?如果您希望此调用会定期失败,请不要使用try / catch块。
答案 10 :(得分:0)
我遵循这种模式来解决这个问题:
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变量来增加或减少此等待时间。