0

I am trying to add a function to a program I am editing. In this program, I have various If statements that use a Microsoft Kinect device to check wherever a person is in a certain position or to check what their head movement is like etc, and depending what they are doing, display a type of feedback.

if (pitch > 10)
{ 
    //display icon
}
else if (pitch <10)
{ 
    //display icon
}
//etc..

At the moment, the icon is turning on/off rapidly depending on the users movement. As this may be confusing for users, I want the condition to match for some seconds before displaying it. e.g. if (pitch > 10) for X seconds then the display icon.

Not sure what the most efficient way of doing this, I have tried a timer and task delay but I think this just delays the results rather than check the condition over a time period.

  • [Task.Delay](https://msdn.microsoft.com/en-us/library/hh194845(v=vs.110).aspx) also see: http://stackoverflow.com/questions/5449956/how-to-add-a-delay-for-a-2-or-3-seconds – Habib Jan 22 '16 at 15:08
  • You have discovered histeresis! This is a well known problem for systems that interact directly with humans. – Paul Keister Jan 22 '16 at 15:11
  • Assuming the above is in some sort of game loop, just store the time when the pitch first went > 10, clear it when pitch goes < 10, and check in each iteration of the loop whether `DateTime.Now` is > X seconds after the initial time. – adv12 Jan 22 '16 at 15:11
  • I had a look at this already but I don't want the task to be delayed, I want the condition to be checked for an X amount of seconds before displaying the icon. – Josh Robertson Jan 22 '16 at 15:11
  • 1
    The first time your condition is true you can spin a timer via `Task.Delay()` for example to schedule the action you want to take followed by a `CancellationToken` something like: `Task.Delay(desireTime, cancellationToken).ContinueWith(ant => //your action)` Then if at anytime before your desiredTime the condition changed, you can use the token to cancel the execution. –  Jan 22 '16 at 15:16
  • I don't know if this was a typo in your code, but `if else` should be `else if` – Nathan C Jan 22 '16 at 15:18

3 Answers3

0

Reorganize your main flow, with some intermediate queue/BlockingCollection+GetConsumingEnumerable where consuming part makes a delay before start processing any item

so very high level pseudocode:

BlockingCollection<IResult> blockingQueue ..

// Producer Task
IResult Process(IInputRequest params)
{
   if (...)
}

// Consuming Task
foreach ( .. blockingQueue.GetConsumerable...)
{
}

to accomodate pause use Task.Delay

Please let me know if you need more details

sll
  • 61,540
  • 22
  • 104
  • 156
0

You can simply count successful checks until needed number is reached

if (pitch > 10)
{ 
    if(counter++ > X)
    {
        //display icon
    }
}
else
    counter = 0; // reset

This is assuming it is possible to estimate number from time. Otherwise you would have to count time (resetting it if you get false condition)

You may implement noise reduction on top of that using same principle to avoid single error to hide icon.

Sinatr
  • 20,892
  • 15
  • 90
  • 319
0

I would use Microsoft's Reactive Framework for this (NuGet "Rx-WinForms" or "Rx-WPF" depending on your UI).

Here's an example of changing the background of a form when hovering over a label for 3 seconds, but reverting it if the mouse moves away.

        var hovers =
            Observable
                .FromEventPattern(h => label1.MouseEnter += h, h => label1.MouseEnter -= h)
                .Select(x => Observable.Timer(TimeSpan.FromSeconds(3.0)))
                .Switch()
                .Select(x => System.Drawing.Color.Red);

        var leaves =
            Observable
                .FromEventPattern(h => label1.MouseLeave += h, h => label1.MouseLeave -= h)
                .Select(x => System.Drawing.Color.White);

        var query = hovers.Merge(leaves);

        var subscription = query.ObserveOn(this).Subscribe(c => this.BackColor = c);
Enigmativity
  • 113,464
  • 11
  • 89
  • 172