2016-06-28 3 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を開発しています。電源が供給されている間、デバイスはON状態を維持し続けます。ユーザーがスイッチをオフにするとすぐに、サーバーへの要求は停止します。

これらのステータスは、デバイスがオンかオフかに関係なく、データベースに更新されます。今は、デバイスの電源が切れたとき(デバイスがリクエストの送信を停止した場合にサーバが何も知らないために複雑になる)を識別することが難しい部分でした。したがって、各デバイスには別個のタイマーがあります。

+0

どのようにクライアントを特定しますか? –

+0

'Elapsed'の中でどのようなコードを実行しますか?私はこれがXYの問題だと思う。 –

+0

私は本当にクライアントを特定する必要はありません....私の実装はクライアントとは関係ありません。実装は、すべてのクライアントが似ており、同じデータを提供すると仮定しています...しかし、他の基準に基づいて複数のタイマーを持つことは可能です。 –

答えて

0

まず、パトリック・ホフマンが私を導き出して、箱から考えてくれてありがとう。 私はそれの中に静的な特性を持つクラスを実装しました。

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のコンテキストにあり、これらはグローバル変数やオブジェクトなどのものではありません。後のリクエストで 'subscription'と 'yyyy'インスタンスにアクセスできません。それは私の信念です...私は間違っているかもしれません。しかし、私は間違いなく** Reactive Framework ** –

+0

を見ていきます。@HirenDesai - 私はあなたのタイマー機能を正しく機能させるために、長時間実行するサービスを実行していると考えていました。このコードは自動的に別のスレッドにプッシュされます。 Rxには、必要に応じて簡単にUIにマーシャリングする方法があります。 – Enigmativity

関連する問題