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

发布于 2024-12-12 18:05:37 字数 307 浏览 0 评论 0原文

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

例如:

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

I've got a class that calls a SOAP interface, and gets an array of data back. However, if this request times out, it throws an exception. This is good. However, I want my program to attempt to make this call again. If it times out, I'd like it to keep making this call until it succeeds. How can I accomplish this?

For example:

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(11

一念一轮回 2024-12-19 18:05:37

您只需要永远循环:

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(非常规方法名称,顺便说一句)抛出ArgumentNullException因为您遇到了错误并且 filter 为空...您真的想要永远占用 100% 的 CPU 吗?

You just need to loop forever:

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

Note that you should almost certainly not actually loop forever. You should almost certainly have a maximum number of attempts, and probably only catch specific exceptions. Catching all exceptions forever could be appalling... imagine if salesOrderList (unconventional method name, btw) throws ArgumentNullException because you've got a bug and filter is null... do you really want to tie up 100% of your CPU forever?

愿与i 2024-12-19 18:05:37

您必须将 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 次 1000 毫秒的重复会产生 1 分 40 秒的最大等待时间,加上操作时间本身。

You must place the try/catch block inside a loop construct. If you wish not to consume 100% of your processor place a Thread.Sleep in the catch block, so everytime an exception occurs, it will wait some time, freeing the processor to do other things.

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

You could also specify exception type, so that only the timeout exception is handled, and other kinds of exceptions pass-through.

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

Note that, TimeOutException should be replaced by the real name of the exception... I don't know if that is the real name.

Also adjust the sleep time, given in millisecs and the amount of repeats, in the case I presented, 100 repeats of 1000ms yields a maximum wait of 1 minute and 40 seconds, plus the operation time itself.

请别遗忘我 2024-12-19 18:05:37

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

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

If you can't change the timeout, the below should work. salesOrdersArray should be initialized to null.

while(salesOrdersArray == null)
{
    try
    {
       salesOrdersArray = MagServ.salesOrderList(sessID, filter);
    }
    catch
    {
       // Log failure
    }
}
一页 2024-12-19 18:05:37

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

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

It its not gernally a good idead to use exceptions as control flow, but this will do what you requested.

bool Caught = true;
while (Caught)
try
{
    salesOrdersArray = MagServ.salesOrderList(sessID, filter);
    Caught = false;
}
catch
{
    Caught = true;
}
灯角 2024-12-19 18:05:37

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

I will use a transactional queue (MSMQ) to store the service call. A loop will dequeue messages and call the service in a TransactionScope, if the call fails the message appear to be still in the queue. An ov erall timeout can be specified by adding a time to expire in the message. This solution is good if you really want a reliable solution since I guessed that calling that operation is critical.

神回复 2024-12-19 18:05:37

尝试

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

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

Try

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

The behavior you are after might cause an endless loop if this never succeeds though...

心清如水 2024-12-19 18:05:37

尝试这样的事情:

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

编辑:哇!伟大的思想都是相似的! :)

Try something like this:

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

Edit: Wow! Great minds think alike! :)

下壹個目標 2024-12-19 18:05:37

尽管我不建议您无限次地执行此操作,但您可以从这句话中创建一个单独的函数:

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

Although I would NOT recommend you to do this for an infinite number of times, you could make a separate function out of that one sentence:

void GoConnect()
{
    try
    {
        salesOrdersArray = MagServ.salesOrderList(sessID, filter);
    }
    catch
    {
        GoConnect();
    }
}
青衫儰鉨ミ守葔 2024-12-19 18:05:37
while(salesOrdersArray == null){

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

这将永远运行,并且使用异常作为循环,速度很慢。有没有一种方法可以修改函数使其返回 null,而不是抛出异常?如果您预计此调用会定期失败,请不要使用 try/catch 块。

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.

素年丶 2024-12-19 18:05:37

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

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

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

我个人认为明智的做法是在每次尝试 Thread.Sleep(1000); 之后再调用 Send(data); 等待几毫秒或几秒——例如,您可以,如果您认为适合您的场景,请使用 attempNumber 变量来增加或减少此等待时间。

I follow this pattern in order to solve this problem:

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

Trying forever seems not to be a good idea as you may end up having an infinite process. If you think you need many attempts to achieve your goal just set huge number here.

I personally think its wise to wait some milliseconds, or seconds after eac attempt Thread.Sleep(1000); before callig Send(data); --- you could for example, use the attempNumber variable to increse or decrease this waiting time if you think its wise for your scenario.

何以心动 2024-12-19 18:05:37
bool repeat = true;
while (repeat)
{
    try
    {
       salesOrdersArray = MagServ.salesOrderList(sessID, filter);
       repeat = false;
    }
    catch
    {
    }
}
bool repeat = true;
while (repeat)
{
    try
    {
       salesOrdersArray = MagServ.salesOrderList(sessID, filter);
       repeat = false;
    }
    catch
    {
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文