C# Web API中线程的最佳实践
我有一个简单的Web API,只有一个C# Web API中线程的最佳实践,c#,multithreading,rest,asp.net-web-api,C#,Multithreading,Rest,Asp.net Web Api,我有一个简单的Web API,只有一个GET控制器。GET控制器读取XML数据并以JSON格式返回 GETAPI应该每分钟都超过一次,但是如果超过1分钟没有GET请求,那么我需要开始备份数据(简单地以XML格式..没什么特别的) 我的获取Api //GET api/ public IHttpActionResult Get() { try { /
GET
控制器。GET控制器读取XML数据并以JSON格式返回
GET
API应该每分钟都超过一次,但是如果超过1分钟没有GET请求,那么我需要开始备份数据(简单地以XML格式..没什么特别的)
我的获取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>
<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>
12
100
XML备份示例:
<CurrentStatus>
<Time Stamp= "20181011133631244">
<price>12</price>
<amount>100</amount>
</Time>
</CurrentStatus>
<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>
12
100
11
120
15
90
我的计划逻辑:我计划声明一个静态变量\u lastAccessedTimestamp
,该变量将由一个单独的线程监控。如果currentTime-\u lastAccessedTimestamp
>1分钟
,则开始备份数据
问题:针对此类场景(或任何其他更好的选项)在Web API中实现线程的良好实践
PS:Web服务将在本地主机IIS服务器上运行。您可以使用类似Hangfire的工具来启动任务,然后该任务可以由某个工具处理。这可能是一个控制台应用程序、另一个web应用程序、Azure功能等等。关键是它位于主web应用程序的外部。然后,你可以立即返回,而不必等待那件事,不管它是什么,结束。您还可以使用SignalR和web workers之类的工具将状态更新推送到客户端。每次请求后,我都会设置/重置一个计时器1分钟。从不同的线程轮询一个变量是没有效率的,还会引发其他问题
更重要的是,您可以使用适当的作业处理库(如Hangfire-),这样您就可以安排一个作业(1分钟后),并在每次请求后重新安排它,以防出现新的请求
请注意,IIS可以随时停止您的进程,您可能需要对此进行调查。
对于实现,您可以使用中间件/过滤器,在每个请求结束时自动执行此操作。无需将其添加到控制器中。在不复制代码的情况下添加多个控制器也更容易。我会使用System.Timers.Timer
来实现这一点。进一步阅读这里->
请知道,我的答案使用依赖注入,但可以很容易地重构为实例化普通类
我将实现一个计时器服务,在您的情况下,它使用1分钟的时间间隔进行配置。我将在下面分享我的计时器实现,它在依赖项注入容器中注册为一个单例,但应该给您一些可以使用的东西
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
现在只需重置控制器中的计时器
[Route("api/[controller]/[action]")]
public class XmlController : Controller
{
private readonly ITimerService _timerService;
public XmlController(ITimerService timerService)
{
//Injected in
_timerService = timerService;
}
[HttpGet]
public IActionResult ProccessXML(object someXMLObject)
{
_timerService.StopTimer();
SomeMethodWithXml(someXMLObject)
//Reset Timer
_timerService.StartTimer();
return Ok();
}
}
你将如何主持这次会议?在Windows服务中?@nvoigt:对不起,我忘了提供那个信息。在我的问题中更新。要使用Hangfire,我是否还需要安装一些服务器(Hangfire服务器)。对不起,我对此不太了解。不,您不需要安装服务器。查看快速入门指南:对于您的情况,Hangfire可能有点过头了。。。