Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/261.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在C#中重复函数,直到它不再抛出异常为止_C#_Exception - Fatal编程技术网

在C#中重复函数,直到它不再抛出异常为止

在C#中重复函数,直到它不再抛出异常为止,c#,exception,C#,Exception,我有一个类,它调用SOAP接口,并返回一个数据数组。但是,如果此请求超时,它将抛出异常。这很好。但是,我希望我的程序再次尝试进行此调用。如果超时,我希望它继续打这个电话,直到成功。我怎样才能做到这一点 例如: try { salesOrdersArray = MagServ.salesOrderList(sessID, filter); } catch { ?? What Goes Here to FORCE the above line of code to rerun until

我有一个类,它调用SOAP接口,并返回一个数据数组。但是,如果此请求超时,它将抛出异常。这很好。但是,我希望我的程序再次尝试进行此调用。如果超时,我希望它继续打这个电话,直到成功。我怎样才能做到这一点

例如:

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

如果您无法更改超时,下面的方法应该可以工作。salesOrdersArray应初始化为
null

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

使用异常作为控制流通常不是一个好主意,但这将满足您的要求

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

您只需要永远循环:

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
,因为您有一个bug并且
filter
为空。。。你真的想永远占用100%的CPU吗?

试试看

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

这将永远运行,并且使用异常作为一个缓慢的循环。有没有一种方法可以修改函数,使其返回null,而不是引发异常?如果您希望此调用定期失败,请不要使用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尝试线程后等待几毫秒或几秒钟是明智的;在呼叫发送(数据)之前;--例如,如果您认为适合您的场景,可以使用attempnumer变量来增加或减少此等待时间。

您必须将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);
    }
}
//迭代100次。。。不是永远!
对于(int i=0;i<100;i++)
{
试一试{
//在这里做你的工作;
break;//如果一切正常,就中断循环
}抓住{
睡眠(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);
    }
}
//迭代100次。。。不是永远!
对于(int i=0;i<100;i++)
{
试一试{
//在这里做你的工作;
break;//如果一切正常,就中断循环
}捕获(超时异常){
睡眠(1000);
}
}
请注意,TimeOutException应替换为异常的真实名称。。。我不知道那是不是真名


还可以调整睡眠时间(以毫秒为单位)和重复次数,在我介绍的情况下,100次1000毫秒的重复产生的最大等待时间为1分40秒,加上操作时间本身。

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

增加超时时间,这样它就不会引发异常?您可以简单地从catch块再次调用该方法,但是-如果服务中断较长时间,会发生什么?是否希望该方法递归运行24小时?我建议将重试次数限制在一定范围内。在所有这些答案中,没有一个人告诉你捕捉更具体的异常。如果您的try块包含获取
salesOrderList
的无效状态的对象,该怎么办?重试永远不会成功。这(可能)会占用系统资源和/或使呼叫应用程序无响应吗?对我来说,这听起来不是最好的解决方案…@Tim:我在添加下面的段落-基本上代码直接回答了问题,但段落解释说这可能不是一个好主意:)+1对于特定的异常,我在编辑过程中输入了我对问题的评论。我知道,我捕捉到了特定的异常、SOAP错误,等等。忘了休息的乐趣,谢谢。@psyklopz:你在catch块中指定异常类型:
catch(SoapException)
etc。你可以在多个catch块中指定多个不同的异常类型。+1:我比Jon的答案更喜欢这个。我认为这使循环的结束条件更加明显。我为什么不呢?我的观点与Jon Skeet的观点相同,在他编写的代码下面不要抛出ex谢谢@asawyer不知道,所以我编辑了我的答案!现在可以了吗?有两件事:1-你几乎永远都不想捕获基异常类,如果你这样做了,它几乎只是为了记录日志,然后再次抛出。2-永远不要抛出基本
异常
类。您正在强制使用代码,使其陷入捕获
异常
的坏习惯。使用更合适的子类,或者创建自己的子类。这很有意义。。。!从来没有这样想过。。。抱歉让你厌烦了,现在呢?
// 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);
    }
}