我需要将一些数据从C# Web应用程序发布到服务。数据本身是在用户使用应用程序时收集的(一种使用统计数据)。我不想在每个用户的请求期间向服务发送数据,我宁愿在应用程序中收集数据,然后在一个单独的线程中发送单个请求中的所有数据,这并不服务于用户的请求(我的意思是用户不必等待服务处理请求)。为此,我需要一种JS的setInterval
模拟-每X秒启动一次函数,以将所有收集的数据刷新到服务。
我发现Timer
类提供了一些类似的(Elapsed
事件)。然而,这允许只运行一次方法,但这不是一个大问题。它的主要困难在于它需要签名
void MethodName(object e, ElapsedEventArgs args)
虽然我想启动candic方法,这将调用web服务(输入参数并不重要):
async Task MethodName(object e, ElapsedEventArgs args)
有人能建议如何解决所描述的任务吗?任何提示赞赏。
3条答案
按热度按时间ryevplcw1#
async
的等价物是一个while
循环和Task.Delay
(内部使用System.Threading.Timer
):传递一个
CancellationToken
很重要,这样你就可以在需要的时候停止这个操作(例如,当您关闭应用程序时)。现在,虽然这与.Net一般相关,但在ASP.NET中,做任何类型的火灾和遗忘都是危险的。有几种解决方案(如HangFire),有些在Fire and Forget on ASP.NET by Stephen Cleary中有记录,有些在How to run Background Tasks in ASP.NET by Scott Hanselman中有记录
yftpprvb2#
下面是一个以周期性方式调用异步方法的方法:
提供的
action
在每个interval
被调用,然后等待创建的Task
。等待的持续时间不影响间隔,除非它碰巧比这更长。在这种情况下,不重叠执行的原则优先,因此,该期间将延长,以匹配等待的持续时间。在异常情况下,
PeriodicAsync
任务将失败完成,因此如果您希望它具有错误弹性,则应该在action
中包含严格的错误处理。用法示例:
**.NET 6更新:**现在可以通过使用新的
PeriodicTimer
类来实现几乎相同的功能,而不会在每个循环上产生Task.Delay
分配的成本:WaitForNextTickAsync
方法返回一个ValueTask<bool>
,这使得这个实现更加高效。不过,效率上的差异非常小。对于每5分钟运行一次的周期性操作,在每次迭代中分配一些轻量级对象应该几乎没有影响。基于
PeriodicTimer
的实现的行为与基于Task.Delay
的实现不同。如果一个动作的持续时间比interval
长,两个实现都会在前一个动作完成后立即调用下一个动作,但是基于PeriodicTimer
的实现的调度程序不会像基于Task.Delay
的实现那样向前滑动。请参阅下面的大理石图,以直观地展示差异:基于
Task.Delay
的实现的调度被永久地向前移动,因为action
的第三次调用持续的时间比interval
长。正如您所看到的,
PeriodicTimer
并不保证action
调用之间的最小间隔。上面的
PeriodicAsync
实现是出于教育目的而故意保持简单的。像参数验证和ConfigureAwait
这样的东西被省略了。roejwanj3#
简单的方法是使用任务和一个简单的循环:
当你想停止线程时,只需中止令牌: