C# 延迟在一两天后停止连续循环程序

C# 延迟在一两天后停止连续循环程序,c#,asp.net-web-api,async-await,task,C#,Asp.net Web Api,Async Await,Task,我有一个.NETWebAPI,在这个API中,我一直在循环中运行Task方法,直到应用程序运行为止 在调用下一个LoopMethod任务之前,我正在使用wait Task.Delay120000。 API连续正常运行1或2天,然后在最后一个日志文件语句log.debugbeforetask Delay.处停止 这意味着在某个时刻任务等待任务。延迟120000;永远不会完成 我有什么遗漏吗 下面是我正在使用的示例代码段格式 我使用递归是因为next LoopMethod参数取决于previous

我有一个.NETWebAPI,在这个API中,我一直在循环中运行Task方法,直到应用程序运行为止

在调用下一个LoopMethod任务之前,我正在使用wait Task.Delay120000。 API连续正常运行1或2天,然后在最后一个日志文件语句log.debugbeforetask Delay.处停止

这意味着在某个时刻任务等待任务。延迟120000;永远不会完成

我有什么遗漏吗

下面是我正在使用的示例代码段格式


我使用递归是因为next LoopMethod参数取决于previous LoopMethod的返回值

public async Task<HttpStatusCode> LoopMethod(string token) 
{
    var responseHttpStatusCode = HttpStatusCode.Unused;

   string NextToken =  await DoSomething();

    log.Debug("Before Task Delay..");
    await Task.Delay(120000);
    log.Debug("After Task Delay..");

    await LoopMethod(NextToken); 

    return responseHttpStatusCode;
}

我不确定这是从Web服务器调用的,还是从客户端代码调用的。如果是Web服务器,您不应该运行这样的任务。应用程序池将回收并最终将其拆除

然而,我的蜘蛛感官告诉我这是客户端,您刚刚用完堆栈,这反过来又导致了StackOverflowException

堆栈溢出的最常见原因是过深或过深 无限递归,函数多次调用自身 存储变量和信息所需的空间 与每个调用关联的数据超过了堆栈上的数据量

如果你真的需要这么做,考虑一下while循环

public async Task<HttpStatusCode> LoopMethod() 
{

    while(true)
    {
       ...

       await Task.Delay(120000);

       if(condition)
          //break or return

       ...
      }
}
或者正如John Wu所建议的,只需使用带状态的计时器

如果这是一个WebServer,考虑使用一个服务来轮询,它被设计为持久和不回收< /P> 根据评论更新


虽然我同意这里使用递归没有任何意义,但请注意 这里没有实际的递归。因为async/await和 延迟永远不会同步完成,每次继续 它有自己的调用堆栈,并且堆栈使用率实际上不会增长。你 可以通过记录Environment.StackTrace的值来说服自己 在方法的开头。也就是说,您仍然可以在 每一次迭代,你都会在某个时候耗尽内存


是的,这段代码就像泰坦尼克号一样,它是一个递归的永无止境的方法,它会停止,因为它可能会耗尽堆栈,并撞上StackOverflowException冰山如果你真的需要这样做,把它放在一段时间内,至少有一些方法可以让它停止exit@TheGeneral啊,好眼力。我没有看到递归。最有可能的问题是,循环在等待任务时停止。延迟120000;每次大约20到30小时后。因此,每次它停止时,我都会再次手动重新启动api调用。如果IIS正在回收api,我如何避免它被回收。我睡了2分钟,因为我正在使用API中的另一个Web服务,我每2分钟给它打一次电话。是否有其他解决方法?可以使用非递归循环进行快速修复。但更好的选择是重构以使用计时器并完全摆脱循环。我使用的是递归,因为下一个LoopMethod参数取决于上一个LoopMethod的返回值。@NikhilShinde是的,这很好,但是如果此方法运行太多次,将使应用程序崩溃。如果需要该参数,只需使用带有循环的局部变量,或带有计时器的字段。如果这是一个Web服务,您可以这样做,您不应该使用长时间运行的任务。网上有很多关于为什么的文档虽然我同意在这里使用递归没有意义,但是请注意这里没有实际的递归。由于async/await和Task.Delay永远不会同步完成的事实,每个continuation都有自己的调用堆栈,并且堆栈使用量实际上不会增加。您可以通过在方法的开头记录Environment.StackTrace的值来说服自己。也就是说,您仍然在每次迭代中创建任务,因此在某些时候会耗尽内存point@TheGeneral这是一个Web服务器,我没有使用任何客户端应用程序来使用此服务。我刚刚查了IIS Web服务器的Evnt日志。它显示webservice停止时的事件日志。Evnt日志1.事件ID 5013-IIS应用程序池可用性-为应用程序池XYZ提供服务的进程在关闭期间超过了时间限制。和事件日志2同时进行。事件ID 5138-IIS协议适配器可用性:为应用程序池提供服务的工作进程未能在分配的时间内停止协议“http”的侦听器通道。数据字段包含错误号。。