2

When the user does something (touch on a StackPanel, in this case), I need to begin a timer of some sort (probably DispatcherTimer as I'm working in WPF) and if another touch happens again within a certain amount of time then I'll call a method. As you can probably guess - this is to implement a double-tap functionality.

I'm assuming the best way to achieve this is through using threads (i.e. a child thread to increment a timespan which can be checked by the Main thread any time the StackPanel is touched again?)

Thanks,

Dan

2 Answers2

6

You do not need to start another thread to do this.

Just take a timestamp of when the first tap happened and use this. You can then calculate the timespan by subtracting this time from the current time:

private DateTime _lastTap;
public void TapHandler()
{
  DateTime now = DateTime.UtcNow;
  TimeSpan span = now - lastTap;
  _lastTap = now;
  if (span < TimeSpan.FromSeconds(1)) {...}
}

Alternatively, as suggested by @DannyVarod, you can use a Stopwatch to achieve the same result (but with more accurate timing):

private Stopwatch _stopwatch = new Stopwatch();
public void TapHandler()
{
  TimeSpan elapsed = _stopwatch.Elapsed;
  _stopwatch.Restart();
  if (elapsed < TimeSpan.FromSeconds(1)) {...}
}
Rich O'Kelly
  • 41,274
  • 9
  • 83
  • 114
  • Perfect. Spot on. Must be too early in the morning for me. Give me 10 mins and I'll mark it as the answer. –  Jan 25 '12 at 09:17
  • Exactly what I was going to answer (without the code sample though). – Nuffin Jan 25 '12 at 09:17
  • Shouldn't it be if (span < TimeSpan.Seconds(1)) {...} ? Also, I'm not able to use TimeSpan.Seconds. The code's easily adapted though, I've got it working. –  Jan 25 '12 at 09:25
  • 1
    You should use System.Diagnostics.Stopwatch instead of DateTime.UtcNow if you want accurate results. – Danny Varod Jan 25 '12 at 09:31
1

The best way is to stick with DispatcherTimer as you first pointed out, as this will ensure you don't need to do any thread marshalling on tick. If you explictly need accuracy and/or background threads, please see the System.Timers.Timer class and System.Threading.Timer class.

A code example which allows differentiation between Single and Double clicks can be found on MSDN (Windows Forms specific, however the principle is the same). Alternatively, please see this example using DispatcherTimer taken from this previous question

   private static DispatcherTimer clickTimer = 
        new DispatcherTimer(
            TimeSpan.FromMilliseconds(SystemInformation.DoubleClickTime), 
            DispatcherPriority.Background, 
            mouseWaitTimer_Tick, 
            Dispatcher.CurrentDispatcher);

    private void Button_MouseDoubleClick(object sender, MouseButtonEventArgs e)
    {
        // Stop the timer from ticking.
        myClickWaitTimer.Stop();

        Trace.WriteLine("Double Click");
        e.Handled = true;
    }

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        myClickWaitTimer.Start();
    }

    private static void mouseWaitTimer_Tick(object sender, EventArgs e)
    {
        myClickWaitTimer.Stop();

        // Handle Single Click Actions
        Trace.WriteLine("Single Click");
    }
Community
  • 1
  • 1
Dr. Andrew Burnett-Thompson
  • 20,980
  • 8
  • 88
  • 178