C# 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 { /

我有一个简单的Web API,只有一个
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可能有点过头了。。。