我有一个仅带有单个GET
控制器的简单Web API。 GET控制器读取XML数据并以JSON格式返回。
GET
API应该每分钟都超过一次,但是如果没有GET请求超过1分钟,那么我需要开始备份数据(仅以XML格式。没什么花哨的)
我的GET Api
//GET api/
public IHttpActionResult Get()
{
try
{
//Read XML
XDocument xDoc = XDocument.Load(@"D:\myfile.xml");
//Convert XML data into JSON string
string jsonStr = JsonConvert.SerializeXNode(xDoc);
JObject json = JObject.Parse(jsonStr);
return Ok(json);
}
catch (Exception ex)
{
return NotFound();
}
}
示例XML:
<CurrentStatus>
<Time Stamp= "20181011133631244">
<price>12</price>
<amount>100</amount>
</Time>
</CurrentStatus>
XML格式的示例备份:
<CurrentStatus>
<Time Stamp= "20181011133631244">
<price>12</price>
<amount>100</amount>
</Time>
<Time Stamp= "20181011133633354">
<price>11</price>
<amount>120</amount>
</Time>
<Time Stamp= "20181011133633204">
<price>15</price>
<amount>90</amount>
</Time>
</CurrentStatus>
我的计划逻辑::我打算声明一个static
变量_lastAccessedTimestamp
,该变量将由一个单独的线程监视。如果currentTime - _lastAccessedTimestamp
> 1 min
,则开始备份数据。
问题:针对这种情况(或其他更好的选择)在Web API中实现线程的良好实践?
PS: Web服务将在本地IIS服务器上运行。
答案 0 :(得分:2)
每次请求后,我都会设置/重置计时器1分钟。从另一个线程轮询的变量效率不高,还会引发其他问题。
更重要的是,您可以使用适当的作业处理lib(例如Hangfire-https://www.hangfire.io/),这样就可以安排作业(在1分钟后),并在每个请求之后重新安排作业,以防出现新的请求。
请注意,IIS可以随时停止您的进程,您可能需要调查一下。 http://docs.hangfire.io/en/latest/deployment-to-production/making-aspnet-app-always-running.html
对于实现,您可以使用中间件/过滤器,该中间件/过滤器会在每个请求结束时自动执行此操作。无需在控制器中添加它。在不重复代码的情况下添加多个控制器也更加容易。
答案 1 :(得分:0)
您可以使用诸如Hangfire之类的功能来触发任务,然后该任务可以由某些东西来处理。可能是控制台应用程序,另一个Web应用程序,Azure功能等等。关键是它在您的主Web应用程序外部。然后,您可以立即返回,而无需等待该事件完成。您还可以利用SignalR和网络工作者等工具将状态更新推送到客户端。
答案 2 :(得分:0)
我将使用arrayOfObjects.sort((a, b) => b.get('date').unix() - a.get('date').unix());
进行此操作。在这里进一步阅读-> Time Class
请知道我的答案使用了依赖注入,但是可以很容易地重构为实例化普通类。
我将实施一个计时器服务,该服务在您的情况下使用1分钟的间隔进行配置。我将在下面共享我的计时器实现,它以单例形式在依赖项注入容器中注册,但应该为您提供一些帮助。
System.Timers.Timer
在应用程序启动时,您必须启动计时器,每分钟之后,它将开始进行数据备份。由于 public class TimerService : ITimerService
{
private readonly System.Timers.Timer _timer;
private DateTime _startTime = DateTime.Now;
private double _timerSettings;
public TimerService()
{
_timer = new System.Timers.Timer
{
AutoReset = true,
Interval = 60000,
};
_timer.Elapsed += (sender, args) =>
{
//Backup Data method here
_startTime = DateTime.Now;
};
}
public double GetTimerInterval()
{
return _timer.Interval;
}
public void StopTimer()
{
if (_timer == null)
{
throw new ApplicationException("Timer not primed.");
}
_timer.Stop();
}
public void StartTimer()
{
if (_timer == null)
{
throw new ApplicationException("Timer not primed.");
}
_startTime = DateTime.Now;
_timer.Start();
}
}
。
现在只需重置控制器中的计时器
AutoReset = true