0

I got a condition, were I have listener which listens for a event.

Trying to do something like below, event handler may receive multiple events, however i need to merge them in one and trigger once.

private static void QueueRequestChanged()
{
     // This may get 1 or 10 events here.
     // want to keep wait for 10 seconds.

     // trigger one event to handle it further
}

I am trying to do this, to avoid dead lock situation. Any suggestion on approach will help.

Thank you.

Rahul K
  • 17
  • 1
  • 9
  • 2
    Use a timer with an interval of 10 seconds. This method should Start the timer and the timer handler should be your "one event to handle it further". – Tom Sep 22 '17 at 18:14
  • 2
    Reactive Extensions is perfect for this sort of thing. – Jason Boyd Sep 22 '17 at 18:18
  • Thank you for response. was curious will it be an issue in difference machine depending on configuration? – Rahul K Sep 22 '17 at 18:19
  • Reactive Extensions is perfect for this sort of thing. Do you have any link or example that will help.. – Rahul K Sep 22 '17 at 18:20
  • Reactive Extensions, for example: [Observable.Throttle](https://msdn.microsoft.com/en-us/library/hh229400(v=vs.103).aspx) – Matthew Watson Sep 22 '17 at 18:30
  • Here is the Reactive Extensions [repo](https://github.com/Reactive-Extensions/Rx.NET) and here is the [book](http://www.introtorx.com/uat/content/v1.0.10621.0/00_Foreword.html). Don't panic - if you know LINQ you will be using reactive extensions effectively in a short time. – Jason Boyd Sep 22 '17 at 18:30

3 Answers3

0

You can have the following code, which will not put your thread in a wait state:

private const Timespan c_maxTime = new Timespan(0, 0, 10);
private static DateTime? s_lastValidEvent;
private static object s_lockObject = new Object();

private static void QueueRequestChanged()
{
     lock (s_lockObject)
     {
          if (!s_lastValidEvent.HasValue || (DateTime.Now - s_lastValidEvent.Value) > c_maxTime)
          {
              // Do whatever the event is supposed to trigger
              s_lastValidEvent = DateTime.Now;
          }
     }
}
Discoverer98
  • 461
  • 3
  • 14
0

You should look into Reactive Extensions (Rx): https://www.nuget.org/packages/System.Reactive/

It makes these kind of things easy if you know LINQ:

using System.Reactive.Linq;
...

System.Reactive.Linq.Observable
    .FromEventPattern<RoutedEventArgs>(btn, "Click")
    .Sample(TimeSpan.FromSeconds(10)) //take the last event for every 10 seconds
    .Subscribe(_ => { MessageBox.Show("clicked!"); });

The above sample code bundles all Clicked events raised by a WPF Button named "btn" during the last 10 seconds and handles only the latest one by displaying a MessageBox.

You need to change RoutedEventArgs to whatever the type of your EventArgs is, "Click" to the actual name of the event and "btn" to the name of the object that raises the event.

mm8
  • 163,881
  • 10
  • 57
  • 88
0

For now, i have did as below, and seems working fine for me.

     var events = 0
     private static void QueueRequestChanged()
    {           
        events++;           
        Task.Delay(10000).ContinueWith(t => Trigger());
    }

    private static void Trigger()
    {
               if(events > 0)
               {
                    events = 0;
                    // do code here
               }
    }

Any better suggestion would be appreciated. Thank you.

Rahul K
  • 17
  • 1
  • 9