1

I had a task to make reflex meter app, and I got and exe as an example. I made it work but I don't get the same results from example I was given and my app, it's like I have 60-70 ms lost somewhere. App is supposed to show a text at random time between 0.5 and 5 seconds and when text shows, the user is supposed to click a button that will stop the stopwatch class I was using here and write it into last and best times.

First I was saving TotalMilliseconds , seconds , milliseconds and minutes as double , and now as TimeSpan, I felt as when I saved it in TimeSpan it reduced time but not enough to be close as example app or even online reflex app. I was thinking about delay between events or even mouse click, but I don't think its supposed to be like 50 60 ms. And if that is the problem how to measure those.

These are start events

private void Start_B_Click(object sender, EventArgs e)
{
    Random rnd = new Random();

    RndTimer.Interval = rnd.Next(500, 5000);
    RndTimer.Start();
}
Stopwatch s = new Stopwatch();
private void RndTimer_Tick(object sender, EventArgs e)
{
    NOW_L.Visible = true;
    s.Reset();
    s.Start();
    Random rnd = new Random();
    RndTimer.Interval = rnd.Next(500, 5000);
}

and this is button click event

public double o;
private void Click_B_Click(object sender, EventArgs e)
{
    if (NOW_L.Visible == true)
    {
        s.Stop();
        TimeSpan ts = s.Elapsed;
        NOW_L.Visible = false;

        if (LtimeRez_LB.Text == "00:00:00" || ts.TotalMilliseconds < class1.m)
        {
            LtimeRez_LB.Text = ts.Minutes.ToString() + ":" + ts.Seconds.ToString + ":" +
                               ts.Milliseconds.ToString();
            BesttimeRez_LB.Text = ts.Minutes.ToString() + ":" + ts.Seconds.ToString + ":" +
                                  ts.Milliseconds.ToString();
            class1.m = ts.TotalMilliseconds;
            o = class1.m;
        }
        else if (ts.TotalMilliseconds > o || ts.TotalMilliseconds == o)
        {
            LtimeRez_LB.Text = ts.Minutes.ToString() + ":" + ts.Seconds.ToString + ":" +
                               ts.Milliseconds.ToString();
        }
        NOW_L.Visible = false;
    }
}

LtimeRez variable is label that is displaying last result and BestTimeRez is best time result, also I used public static double variable called m

Sudsy1002
  • 588
  • 6
  • 21
LordRed
  • 31
  • 4

2 Answers2

1

Use the MouseDown event of the Button instead of the Click event. The Click event will only be triggered some time later than when the user pressed the mouse button on the control because it first waits for the user to also release the mouse button and because it also has to perform some internal tasks first (redrawing the button, validation checks).

Additional notes on the code:

Don't create a new instance of the Random class each time. Create one instance once and reuse it all the time. See How do I generate a random int number in C#?

In the Timer Tick function, only start the Stopwatch after setting the timer interval. The button will actually only become visible when the code leaves that function and has a chance again to process Windows messages.

Please give o and m some meaningful names. You don't need both variables. They always have the same value. You only need one of them.

In CLick_B_Click, you don't need the if in the else part.

In the current version of the code, when the user does not click immediately, the timer click event can happen multiple times before the user clicks the button, resetting the stopwatch too early...

NineBerry
  • 26,306
  • 3
  • 62
  • 93
  • Thank You , this seemed to fix the problem and I was able to achieve 40 to 50 ms less that before, is there any other tip I could do to reduce latency even more – LordRed Dec 28 '18 at 13:53
  • So I changed the way is write string into this LtimeRez_LB.Text = String.Format("{0}:{1}:{2}", ts.Minutes, ts.Seconds, ts.Milliseconds); but as You said it doesn't make any difference in this case cause I saved data before so I save time even more. But I don't quite understand why wouldn't start stopwatch as soon as I can after NOW label is shown , so I could save even more time not having to wait for timer interval to be changed again – LordRed Dec 28 '18 at 14:16
  • @LordRed Setting Visible to true on a control doesn't show it immediately to the user. The control will still be invisible until your code is terminated and the application is idle and has the time to draw the control. – NineBerry Dec 28 '18 at 14:30
  • I got it now , Thank You for your time. – LordRed Dec 28 '18 at 15:10
-1

One problem I am seeing here is string concatenation in you code. In C# world, while concatenating you should use String.Format() method. Using plus operator to join the string will add delay. So use below line to form string -

LtimeRez_LB.Text = String.Format("{0}:{1}:{2}", ts.Minutes, ts.Seconds, ts.Milliseconds);  

~Nilesh

Nilesh Shinde
  • 380
  • 1
  • 13