How to capture a time interval while waiting for user input? - c#

I have Form with a Timer1, and it set to 10Sec.
There is a KeyDown event - when the user press "Enter", I would like to save in "ans" the time duration that past in the 10S interval before it ends.
For Example: If i starting the timer1 now, and after 3Sec, I'm pressing Enter, ans = 3. and if I didnt press any key, ans will be equal to 10.
I have this code:
if (e.KeyCode == Keys.Enter)
{
ResponseTimeList.Add(timer1.Interval);
}
*ResponseTimeList is:
public List<double> ResponseTimeList = new List<double>();
How can i improve it?
Thanks.

Well, to start out with, Timer is not what you want to use. The timer class is designed to fire off events at a pre-defined interval of time; for example, you might use a timer to update a text box on a form every 10 seconds.
Instead, what you wish to do is use a stopwatch (System.Diagnostics.Stopwatch). Call Stopwatch.Start() whenever you want to start timing. When the user presses enter, simply call Stopwatch.Stop() and then get the time interval that has elapsed in seconds.
Finally, for the 10-second logic, you will need to use something like this (a conditional evaluation):
var timeToDisplay = Stopwatch.ElapsedMilliseconds > 10000 ? 10 : Stopwatch.ElapsedMilliseconds/1000

You can use Tick event of Timer.
bool isPressed = false;
Timer timer1 = new Timer() { Interval = 10000};
timer1.Tick += (s, e) =>
{
if (!isPressed)
ResponseTimeList.Add(timer1.Interval);
isPressed = false;
};
And when key pressed:
if (e.KeyCode == Keys.Enter)
{
ResponseTimeList.Add(timer1.Interval);
isPressed = true;
}

Related

Stopping DispatcherTimer with a button click

When I click my stop button, my timer is still counting down, even though I tell it to stop.
My current relevant code:
I'm naming the timers here, as I need to access them for a stop/start all button as well.
namespace Row_Interface
{
public partial class MainWindow : Window
{
//Declare the timers here, so the stop all button can access them as well
DispatcherTimer motorTimer_1 = new DispatcherTimer();
TimeSpan motorCycleTime_1 = TimeSpan.FromSeconds(0);
When I click the on button, the IndividualTestStart method is called & passed the relevant parameters:
public void motorOnBtn_1_Click(object sender, RoutedEventArgs e)
{
IndividualTestStart(motorOnBtn_1, motorOffBtn_1, motorTimer_1, motorCycleTime_1, timeUntilmotorCycle_1, motorTestCycles_1);
}
When I click the off button, I'm wanting to stop that timer so the cycle never finishes:
private void motorOffBtn_1_Click(object sender, RoutedEventArgs e)
{
motorTimer_1.Stop();
motorOnBtn_1.IsEnabled = true; //Enables the start test button
motorOffBtn_1.IsEnabled = false; //Disables the stop test button
}
This is called when I click start. I'll eventually have something similar for the stop button, but I'm taking things one step at a time:
private void IndividualTestStart(Button startButton, Button stopButton, DispatcherTimer dispatcherTimer, TimeSpan timeSpan, TextBox timeRemaining, TextBox cycleCount)
{
stopButton.IsEnabled = true; //Enables the stop button
//Set the time to run. This will be set from the database eventually.
timeSpan = TimeSpan.FromSeconds(10);
//Set up the new timer. Updated every second.
dispatcherTimer = new DispatcherTimer(new TimeSpan(0, 0, 1), DispatcherPriority.Normal, delegate
{
timeRemaining.Text = timeSpan.ToString("c"); //Sets the text in the textbox to the time remaining in the timer
startButton.IsEnabled = false; //Disables the start test button once the test is started
if (timeSpan == TimeSpan.Zero) //Checks to seee if the time has run out
{
dispatcherTimer.Stop(); //Stops the timer once the time has run out
startButton.IsEnabled = true; //Enables the start test button
int initialCycleCount = 0;
initialCycleCount++;
cycleCount.Text = initialCycleCount.ToString();
stopButton.IsEnabled = false;//Disables the stop button
}
timeSpan = timeSpan.Add(TimeSpan.FromSeconds(-1)); //Subtracts one second each time the timer "ticks"
}, Application.Current.Dispatcher); //runs within the UI thread
dispatcherTimer.Start(); //Starts the timer
}
}
When I click the stop button, I expect the timer in the textbox to stop counting down. However, it just keeps on ticking. When I click stop, the start button is re-enabled, so I know that it's triggering the code in the event handler. But it isn't stopping the timer.
Not starting a new timer now.
New code:
public void motorOnBtn_1_Click(object sender, RoutedEventArgs e)
{
IndividualTestStart(motorOnBtn_1, motorOffBtn_1, motorTimer_1, motorCycleTime_1, timeUntilmotorCycle_1, motorTestCycles_1);
}
private void IndividualTestStart(Button startButton, Button stopButton, DispatcherTimer dispatcherTimer, TimeSpan timeSpan, TextBox timeRemaining, TextBox cycleCount)
{
stopButton.IsEnabled = true; //Enables the stop button
//Set the time to run. This will be set from the database eventually.
timeSpan = TimeSpan.FromSeconds(10);
{
timeRemaining.Text = timeSpan.ToString("c"); //Sets the text in the textbox to the time remaining in the timer
startButton.IsEnabled = false; //Disables the start test button once the test is started
if (timeSpan == TimeSpan.Zero) //Checks to seee if the time has run out
{
dispatcherTimer.Stop(); //Stops the timer once the time has run out
startButton.IsEnabled = true; //Enables the start test button
int initialCycleCount = 0;
initialCycleCount++;
cycleCount.Text = initialCycleCount.ToString();
stopButton.IsEnabled = false;//Disables the stop button
}
timeSpan = timeSpan.Add(TimeSpan.FromSeconds(-1)); //Subtracts one second each time the timer "ticks"
}; //runs within the UI thread
dispatcherTimer.Start(); //Starts the timer
}
The problem in your code is that you initialize motorTimer_1 with a DispatcherTimer that doesn't do anything, then you pass motorTimer_1 in as the dispatcherTimer parameter, and then you replace the value of the parameter with a newly created, different DispatcherTimer.
The new timer works fine, but when you call stop on motorTimer_1, nothing happens, because that's not the one that's running. You could simply assign the new DispatcherTimer directly to motorTimer_1 in IndividualTestStart(), but you've gone to great trouble to parameterize everything in IndividualTestStart() so it can work with different DispatcherTimers.
Instead, here's what we'll do: There is no reason to pass in a DispatcherTimer. IndividualTestStart() must create the DispatcherTimer in order to initialize it. OK, let's run with that. It will create a new one and return it.
private DispatcherTimer IndividualTestStart(Button startButton, Button stopButton,
TimeSpan timeSpan, TextBox timeRemaining, TextBox cycleCount)
{
stopButton.IsEnabled = true; //Enables the stop button
//Set the time to run. This will be set from the database eventually.
timeSpan = TimeSpan.FromSeconds(10);
// Set up the new timer. Updated every second.
var dispatcherTimer = new DispatcherTimer(new TimeSpan(0, 0, 1), DispatcherPriority.Normal, delegate
{
timeRemaining.Text = timeSpan.ToString("c"); //Sets the text in the textbox to the time remaining in the timer
startButton.IsEnabled = false; //Disables the start test button once the test is started
if (timeSpan == TimeSpan.Zero) //Checks to seee if the time has run out
{
dispatcherTimer.Stop(); //Stops the timer once the time has run out
startButton.IsEnabled = true; //Enables the start test button
int initialCycleCount = 0;
initialCycleCount++;
cycleCount.Text = initialCycleCount.ToString();
stopButton.IsEnabled = false;//Disables the stop button
}
timeSpan = timeSpan.Add(TimeSpan.FromSeconds(-1)); //Subtracts one second each time the timer "ticks"
}, Application.Current.Dispatcher); //runs within the UI thread
dispatcherTimer.Start(); //Starts the timer
return dispatcherTimer;
}
public void motorOnBtn_1_Click(object sender, RoutedEventArgs e)
{
if (motorTimer_1 == null)
{
// Create/initialize a new timer and assign it to motorTimer_1
motorTimer_1 = IndividualTestStart(motorOnBtn_1, motorOffBtn_1,
motorCycleTime_1, timeUntilmotorCycle_1, motorTestCycles_1);
}
else
{
// It's already there, just start it.
motorTimer_1.Start();
}
}
Since this is WPF, you'll want to write a viewmodel class TimerThing (think of a better name) that owns a DispatcherTimer, two commands to start it and stop it, and a public bool property that indicates whether it's running or not. IndividualTestStart() should be a method of that class. The parent viewmodel will have have an ObservableCollection<TimerThing> containing an arbitrary number of TimerThings, which will be displayed in an ItemsControl with an ItemTemplate that creates buttons bound to the Start and Stop commands. The above code will look very different, since none of the C# code will know anything about buttons: Instead, the buttons in the item template XAML will be enabled/disabled by bindings.

How to activate the timer?

I'm new in asp.net. Im develping a web-baised application that should prevent the user if he tried to login three times with wrong password.
I will disable the login button for 10 minutes then I will enable it.
this is the interface
and this is the timer code
protected void timer1_tick(object sender, EventArgs e)
{
timer--;
if (timer == 0)
{
Button1.Enabled = true;
Timer1.Enabled = false;
Label1.Visible = false;
}
}
but when I run the application, after 10 minutes it's refresh the page without enable the login button
If you are using a System.Tmers.Timer then simply call:
Timer1.Start();
If you are using a System.Threading.Timer then this should start immediately. The third argument in the constructor is the dueTime which is:
The amount of time to delay before callback is invoked, in milliseconds. Specify Timeout.Infinite to prevent the timer from starting. Specify zero (0) to start the timer immediately.
Source
So if this is non-zero your timer wont fire for the first time until after both the dueTime and period have elapsed. So if you have:
var timer1 = new Timer(callback, state, 10000, 10000);
the first time this will fire will be after 20 seconds and then it will fire every 10 seconds thereafter. If you want it to fire every 10 seconds then you need to specify 0 as the dueTime:
var timer1 = new Timer(callback, state, 0, 10000);

Reset the count of inactive time in C#

I found this post and created a class that used it to detect inactive time and it works great. I set it for one minute and after one minute I can get it to "do stuff". What I am trying to do is only do something every "x" minutes of inactive time; i.e. every 5 minutes do this if things have been inactive and do not repeat again 'til X time has elapsed.
Now, I could set my timer to fire every 5 minutes instead of every second, but I would like to be able to "reset" the count of inactive time instead. Any suggestions?
This is for using the DispatchTimer in C# and WPF.
Just create a class level variable, increment it on your timer, and reset it when you get activity. Create a timer, say tmrDelay with an increment of 10000 milliseconds, and a button, btnActivity to reset the count, and do this:
private int tickCount = 0;
private const int tick_wait = 30;
private void tmrDelay_Tick(object sender, EventArgs e)
{
tickCount++;
if (tickCount > tick_wait)
{
DoSomething();
tickCount = 0;
}
}
private void btnActivity_Click(object sender, EventArgs e)
{
tickCount = 0;
}
It sounds like you want something like the following:
static DispatcherTimer dt = new DispatcherTimer();
static LastInput()
{
dt.Tick += dt_Tick;
}
static void dt_Tick(object sender, EventArgs e)
{
var timer = (DispatcherTimer)sender;
var timeSinceInput = TimeSpan.FromTicks(GetLastInputTime());
if (timeSinceInput < TimeSpan.FromMinutes(5))
{
timer.Interval = TimeSpan.FromMinutes(5) - timeSinceInput;
}
else
{
timer.Interval = TimeSpan.FromMinutes(5);
//Do stuff here
}
}
This will poll every 5 minutes to see if the system has been idle for 5 minutes or more. If it's been idle for less than 5 minutes it will adjust the time so that it will go off again at exactly the 5 minute mark. Obviously then if there has been activity since the timer was set it will be adjusted again so it will always aim for 5 minutes of idleness.
If you really want to reset the active time then you will actually need to trigger some activity either by moving the mouse or sending a keypress

Timer C# Stop() doesn't really stop

I have a form which includes a textbox showing the time passing with an interval of 1 second up till 2 minutes. It is working ok. However I need the timer to stop when a round of game is over and start again when a button from another form is clicked. So I have _timer.Stop() in the timer_tick event handler and _timer.Start() in the button click event handler of Form 2.
My problem is that the timer then starts from how much time passes until I press the button on the other form and not from 0:00 again. Any Ideas?
This is the code regarding the timer:
private DateTime _myDateTime;
private System.Windows.Forms.Timer _timer;
private DateTime newDate;
public Tournament()
{
_timer = new System.Windows.Forms.Timer();
_timer.Interval = 1000;
_timer.Tick += Timer_Tick;
_myDateTime = DateTime.Now;
newDate = new DateTime();
newDate = newDate.AddMinutes(2.00);
_timer.Start();
InitializeComponent();
}
void Timer_Tick(object sender, EventArgs e)
{
var diff = DateTime.Now.Subtract(_myDateTime);
this.textBox1.Text = diff.ToString(#"mm\:ss");
DateTime dt = Convert.ToDateTime(diff.ToString());
if (newDate.Minute == dt.Minute)
{
_timer.Stop();
_myDateTime = DateTime.Now;
displayPointsOrResults();
this.textBox1.Text = diff.ToString(#"mm\:ss");
}
}
In displayPointsOrResults() I am creating instance of another form Points() so in Points form I have button 1 and I have this in its event handler apart other things which does not concern the timer: tournament.Timer1.Start();
Where I am getting the timer from the tournament class and starting it again.
What am I doing wrong?
My problem is that the timer then starts from how much time passes until I press the button on the other form and not from 0:00 again.
Well yes, it would - you're resetting _myDateTime when you stop the timer:
_timer.Stop();
_myDateTime = DateTime.Now;
You should move that second line to the point where you restart it.
Note that your title is incorrect - the timer really is stopping, in that it's not ticking any more. The timer isn't actually performing the timing, if you see what I mean - it's just a way of invoking an event handler regularly. The problem is within the event handler itself.
Ah the global vars, blessing and curse together.
Do you have resetted the _myDateTime to DateTime.Now, when you press the button?
When you stop the timer and restart it, should set the datetime to now.
_myDateTime = DateTime.Now;

Problem in pausing/resuming Timer

I have a maze game. After you press Enter, you can enter a cheat code, also, the timer will pause. But after entering the code, my timer resumes but it decrements 3x each second. Here's the condition for pressing Enter:
// gt.setTimer() is called at the moment the maze started
// I'm using getch to trap inputs
else if (move == 13) //Reads if Enter is pressed
{
pause = 1; //A Flag saying that the timer must be paused
gt.setTimer(pause); //Calls my setTimer() method
Console.Write("Enter Cheat: ");
cheat = Console.ReadLine();
pause = 0; //A Flag saying that the timer should resume
gt.setTimer(lives, pause); //Calls again the Timer
}
Here's my setTimer() code:
static System.Timers.Timer t = new System.Timers.Timer();
static int gTime = 300;
public void setTimer(int pause)
{
t.Interval = 1000; // Writes the time after every 1 sec
if (pause == 1)
t.Stop(); // Stop the timer if you press Enter
else
t.Start(); // Starts the timer if not
t.Elapsed += new ElapsedEventHandler(showTimer);
}
public static void showTimer(object source, ElapsedEventArgs e)
{
Console.Write("Time " + gTime); //Writes time
gTime--; //Decrements the time
}
Is there something wrong? Am i missing something?
The problem is in the last line of the setTimer method. The timer handler should be registered just once after calling constructor, and not in the setTimer. On the elapsed timer event, the handler is called the number of times it has been registered. Thus the more you use operator += more times it being called.
Every time when you do:
t.Elapsed += new ElapsedEventHandler(showTimer);
you add one more event handler to this event
This strind runing only once, in par code where you initialise timer

Categories

Resources