2016-06-28 48 views
0

我正在开发一个Web API(它工作得很好)。少了什么东西? 这里是Get行动的示例代码:在x秒后触发一个事件,但在执行之前也取消它。

public IEnumerable<xxxx> Get() 
{   
    IEnumerable<xxxx> yyyy = new List<xxxx>(); 
    //get yyyy from database 
    timer = new Timer(); 
    timer.AutoReset = true; 
    timer.Enabled = true; 
    timer.Interval = 5000; //miliseconds 
    timer.Elapsed += timer_Elapsed; 
    timer.Start(); 
    return yyyy; 
} 
void timer_Elapsed(object sender, ElapsedEventArgs e) 
{ 
    //code to be executed when timer elapses... 
} 

因此,一旦接收到请求,定时器将被初始化,并且将在火5秒间隔Elapsed事件。在这样下去未来后续请求....

预期的行为是这样的:

  1. 初始化请求-1
  2. 初始化定时器-1
  3. 如果来自同一客户的请求被接纳5秒钟,定时器不得触发流逝的事件。
  4. 如果在5秒内没有收到来自同一个客户端的请求,定时器应该流逝并且触发事件。

此外,计时器与客户无关。

这是与此有关的进一步的业务场景.... 我正在开发一个Web API,开机时将被电子设备使用。只要电源可用,设备将继续发送它的状态。只要用户关闭交换机,就停止对服务器的请求。

无论设备是打开还是关闭,这些状态都会更新到数据库中。现在棘手的部分是确定设备何时关闭(因为如果设备停止发送任何请求,服务器不知道任何事情)。所以每个设备都有一个单独的计时器。

+0

您如何识别客户? –

+0

你想在“Elapsed”中运行什么代码?我认为这是一个XY问题。 –

+0

我真的不需要识别客户端....我的实现与客户端无关。该实施假设,所有客户都是相似的,并且将被提供相同的数据...不过,可以根据其他标准设置多个计时器 –

回答

0

首先,谢谢你@Patrick Hofman指导我并思考开箱... 我实现了一个里面有静态属性的类。

public class DeviceContainer 
{ 
    public static List<DevTimer> timers=new List<DevTimer>(); 
} 
public class DevTimer:Timer 
{ 
    public string Identifier {get; set;} 
    public bool IsInUse{get; set;} 
} 

,然后在上面的代码(有问题),我做了如下改变:

public IEnumerable<xxxx> Get(string Id) 
{   
    //Check if timer exists in 
    if(!DeviceContainer.timers.Any(s=>s.Identifier.Equals(Id))) 
    { 
     //Create new object of timer, assign identifier =Id, 
     //set interval and initialize it. add it to collection as 
     var timer = new DevTimer(); 
     timer.AutoReset = true; 
     timer.Enabled = true; 
     timer.Interval = 5000; //miliseconds 
     timer.Elapsed += timer_Elapsed; 
     timer.IsInUse=true; 
     timer.Identifier=Id;    
     DeviceContainer.timers.Add(timer); 
     timer.Start(); 
    } 
    else 
    { 
     //Code to stop the existing timer and start it again. 
     var _timer=DeviceContainer.timers.FirstOrDefault(s=>s.Identifier.Equals(Id)) 
         as DevTimer; 
     _timer.Stop(); 
     _timer.Start(); 
    }   

} 
void timer_Elapsed(object sender, ElapsedEventArgs e) 
{ 
    //code that will turn off the device in DB 
} 

我不张贴整个代码,这里不是目的。

0

我会为此使用Microsoft的Reactive Framework。

下面的代码:

IEnumerable<xxxx> yyyy = new List<xxxx>(); 

Subject<Unit> clientRequestArrived = new Subject<Unit>(); 

IDisposable subscription = 
    clientRequestArrived 
     .Select(_ => Observable.Interval(TimeSpan.FromSeconds(5.0))) 
     .Switch() 
     .Subscribe(_ => 
     { 
      //code to be executed when timer elapses... 
      //directly access `yyyy` here 
     }); 

所有你需要做的是每一个用户请求进入,这将是足以让此代码复位定时器时间呼叫clientRequestArrived.OnNext(Unit.Default);

如果您想完全停止定时器,只需拨打subscription.Dispose()即可。

+0

2这里的问题,这个代码是否会在阻塞我的UI或当前的HttpRequest的主线程上运行?其次,上面的代码是专门针对ASP.NET的上下文,它是无状态的,并且这些都不是全局变量或对象。 “订阅”和“yyyy”实例在后续请求中将不可访问。这是我的信念......我可能也错了。但我肯定会考虑** Reactive Framework ** –

+0

@HirenDesai - 我曾想过,您正在运行某种长时间运行的服务来让您的计时器正常工作。而这段代码将被自动推送到一个单独的线程。如果需要的话,Rx有很多方法可以轻松地回复到用户界面。 – Enigmativity

相关问题