I am learning C# and I am coding a simple auto typer, and I am trying to make it so users' can set their own interval. I tried using:
timer1.Interval = textbox1.Text;
but that doesn't seem to be working. I put that code in a button.. How do I get this to work? And why isn't it working?
You could use something like this:
int value;
// if it is really a value
if (int.TryParse(textbox1.Text, out value))
{
// if the value is not negativ (or you can enter the lower boundary here)
if (value > 0)
{
timer1.Interval = value;
}
}
As Steve mentioned in his comment, you need to connect a callback function to the timer1.Elapsed event (Attention: The name of the event differs depending on the timer you are using. It could also be timer1.Tick). You would do this by using the following code:
timer1.Elapsed += TimerElapsedCB;
and you need to define the callback function itself:
private void TimerElapsedCB(object sender, ElapsedEventArgs e)
{
// Do something here ;-)
// (e.g. access the signal time by using e.SignalTime)
}
try this :
Timer timer1 = new Timer();
timer1.Interval = int.Parse(textbox1.Text);
but keep in mind that user must enter a number , so you might need to handle the case when the user enter wrong data .
Edit :
You might use TryParse to make sure it's a number :
int myInt = 0;
Timer timer1 = new Timer();
bool parsed = int.TryParse(textbox1.Text,out myInt);
if (parsed)
{
timer1.Interval = myInt;
}
Related
I'm trying to create a recursive call to a method but receive error:
Cannot evaluate expression because the current thread is in a stack
overflow state
Just a bit of a background, I'm migrating a PowerBuilder app. to a C#.NET windows app., the PB app. has a timer that is done programmatically which will execute the main method at a specific time. The PB code runs on two machines, one timer is set at the '0' mark and on machine #2, it is set at the 30 second mark.
PB code below:
ue_wait event:
gi_offset = //Global variable set at the application open event, equivalent to program.cs - main event. Will be 0 or 30 depending on the machine.
li_difference = Integer( String( Now(), 'ss')) //Gets the seconds from the current date time.
DO UNTIL li_difference = gi_offset
ls_status = 'current second: ' + String( Now(), 'ss') + ' starting on:' + String( gi_offset)// Builds a string to display in a static text control in PB, label in C#.
IF st_status.Text <> ls_status THEN st_status.Text = ls_status
Yield()
li_difference = Integer( String( Now(), 'ss'))
LOOP
//execute main processing method.
ue_action().
//End of event
ue_action event
Do main processing.
Call ue_wait()
My C# code below:
private void Form1_Shown(Object sender, EventArgs e)
{
ue_wait();
}
private void wf_actions_Load(object sender, EventArgs e)
{
//Should fire after all of the form has loaded.
Shown += Form1_Shown;
}
private void ue_wait()
{
long todays_date_in_seconds = DateTime.Now.Second;
long ll_global_offset = 0;
string ls_status = "";
todays_date_in_seconds = DateTime.Now.Second;
while (!(todays_date_in_seconds == ll_global_offset))
{
ls_status = "Current second: " + DateTime.Now.Second.ToString() + " starting on: " + ll_global_offset.ToString();
lbl_status.Text = ls_status;
todays_date_in_seconds = DateTime.Now.Second;
}
ue_action();
}
private void ue_action()
{
//After the main processing is done, it goes back to ue_wait().
ue_wait();
}
So I have tried the two possibilities that I found on the Inet:
this.Shown += new System.EventHandler(this.Form1_Shown);
this.Activated += AfterLoading;
However when calling ue_action I get the error below in the ue_wait event for both...
{Cannot evaluate expression because the current thread is in a stack
overflow state.}
Fails on the first line: long todays_date_in_seconds = DateTime.Now.Second;
I found the .NET timer but it does not allow you to set the Start at a specific point in time, ie: seconds, Timer.Start() = 0 mark or Timer.Start() = 30 second mark (30000 milliseconds). The interval is one part that would work as I could set it to execute every 60 seconds.
After doing some googling, because there is 'recursive' programming, this is causing the 'Stack Overflow', how can I avoid the 'Stack Overflow' in the .NET environment or would there be another way to do what I need to do in the C#.NET environment?
The simplest approach would be to use a 1s System.Windows.Forms.Timer, that's a no brainer:
// timer initialization, somewhere
timer = new System.Windows.Forms.Timer();
timer.Interval = 1000;
timer.Tick += Timer_Tick;
DateTime? _lastHandledTimestamp = null;
private void Timer_Tick(object sender, EventArgs e)
{
// get current timestamp
var currentTimestamp = DateTime.UtcNow;
var currentSecond = currentTimestamp.Second;
// not the correct second yet?
if (currentSecond <= TARGET_SECOND)
return;
// truncate seconds and check if we already handled this hh:mm
var flooredToNearestMinute = currentTimestamp.AddSeconds(-currentSecond);
if (_lastHandledTimestamp.HasValue &&
_lastHandledTimestamp.Value >= flooredToNearestMinute)
return;
// if we're here, we are good to go
_lastHandledTimestamp = flooredToNearestMinute;
DoStuff();
}
If you want to avoid triggering the tick event every second, use a System.Threading.Timer instead, and use its Timer.Change method to calculate the next time it needs to fire on each iteration.
Groo, thanks for the input on the timer, I tweaked it for what I need to do.
private void timer1_Tick(object sender, EventArgs e)
{
string ls_status = "";
var currentSecond = DateTime.Now.Second;
ls_status = "Current second: " + currentSecond.ToString() + " starting on: " + Il_offset.ToString();
lbl_status.Text = ls_status;
if (currentSecond == Il_offset && Ib_processing_completed)
{
//Main processing method
ue_action();
}
}
In the Tick event, I populate an instance variable of offset in the PageLoad, in this case it will be 1 or 31 and set a Boolean variable to true in the ue_action event after successful processing.
To get rid of the original problem, instead of doing recursive programming and looping, the Tick event was recommended instead which meets my needs.
Thank you, the .NET learning curve begins.
William.
Hi all I'm still new to the c# events and timers but it seems I have a bug that baffles me despite following seemingly working code online. I have a simple search function that is triggered after a timer elapses. Before that function triggers I set the result title to "Search in progress..." and at the end of the process i expect it to change to "1152 results found". But the label doesn't change eventhough in debug i hit the code sets it and i even see that the searchresultTitle.Text value is changed and the "list" actually contains 1152 items. The website just doesnt reflect it, is there something wrong with the way I setup the timers or am I missing something?
protected void StartSearchClick(object sender, EventArgs ev)
{
String textVal = Request["SearchBox"];
textVal = textVal.Replace('*', '_');//to support * as wildcard
String publicChoice = PublicChoice.SelectedValue;
int iChoiceVal = 1;
Int32.TryParse(publicChoice, out iChoiceVal);
SearchResultTitle.Text = "Search in progress...";
System.Timers.Timer aTimer = new System.Timers.Timer(1000);
aTimer.Elapsed += (s, e) => ReadPublishedLessons(textVal, iChoiceVal);
aTimer.AutoReset = false;
aTimer.Start();
}
private void ReadPublishedLessons(string namePart, int iPublic)
{
//null check
if (namePart == null)
return;
eon.LessonInfo[] list = WsAdmin.GetLessonList(namePart, iPublic);
SearchResultTitle.Text = list.Length + " results found";
}
Answered by Bharadwaj in the comments...
In case of asp.net, the html is sent back to the client side only after a post back or a partial post back. At the end of your event trigger call, the html which is ready is already reached to the client with Search in progress... message. But when you try to change the value of label, it is changing and it is still at server only. – Bharadwaj Jul 15 '16 at 4:45
Trying to make a simple C# program where a ship goes through several "checkpoints" and when it's bounds interesect, it adds to the players score, then game ends when you reach the final checkpoint. Can't figure out how to make the score go up and print to the label each time. Thanks!
UPDATE: I can get my boxes to increase the score once, but not on all the other pictureboxes. Also, when I hit the final "spaceport" picturebox I get stuck in a messagebox redirect loop. How do I solve these 2 things? Tutors at school are no help.
public partial class consoleForm : Form
{
public consoleForm()
{
InitializeComponent();
}
private void consoleForm_Load(object sender, EventArgs e)
{
}
private void outputBox_TextChanged(object sender, EventArgs e)
{
}
private void timer1_Tick(object sender, EventArgs e)
{
int score = (0);
if (ship.Bounds.IntersectsWith(wormhole1.Bounds))
{
score += (1);
userScore.Text = score.ToString();
this.Refresh();
}
else if (ship.Bounds.IntersectsWith(wormhole2.Bounds))
{
score += (1);
userScore.Text = score.ToString();
this.Refresh();
}
else if (ship.Bounds.IntersectsWith(wormhole3.Bounds))
{
score += (1);
userScore.Text = score.ToString();
this.Refresh();
}
else if (ship.Bounds.IntersectsWith(wormhole4.Bounds))
{
score += (1);
userScore.Text = score.ToString();
this.Refresh();
}
if (ship.Bounds.IntersectsWith(spaceport.Bounds))
{
MessageBox.Show("you win");
this.Refresh();
}
}
The problem you've got is, that you're only doing this check once when the form loads, and never again.
Remove the logic from the consoleForm_Load event, and put it in your own method, called CheckScore(), or something else meaningful.
What would be good is to use a timer to check for the intersection every, let's say 100ms (0.1 seconds).
Create a timer:
In your constructor for the consoleForm, create a timer and a handler for it, then Start it. *You could even put it in your already-existing consoleForm_Load event - your choice :)
Like so:
public consoleForm()
{
var timer = new System.Timers.Timer(100); // Create a timer that fires every 100ms (0.1s)
timer.Tick += OnTimer_Tick;
timer.Start();
}
Add an event for the Tick event of the timer:
The OnTimer_Tick you can either "auto create" from VS, or add yourself:
private void OnTimer_Tick(object sender, ElapsedEventArgs e)
{
CheckScore(); // Call your logic method to check the score
}
Do the logic:
If you haven't already, make sure you've created the CheckScore() method using your original logic (that used to be in the consoleForm_Load event).
Final note:
I would seriously consider tidying up your CheckScore() (or whatever you like to call it) method, but that's just me :)
Further final note: there are loads of other ways of creating timers; I'm just being nice and using the most basic use of a Timer in WinForms :)
Hope this helps!
MORE!!!
At the moment, you're creating a new "score" every time you call the CheckScore() method.
In order to store your score, create a private field called _score or similar:
private int _score = 0;
Then, whenever you're adding to the user's score, reference the _score field, and use that to calculate and display:
_score++;
// or your own logic
_score += 20; // etc. etc.
// At the bottom of your logic,
// when you're ready to display the score:
userScore.Text = "Your score: " + _score;
Then, you can reference the _score wherever else you need it in your form.
Such as re-setting it:
private void ResetScore()
{
_score = 0;
}
or checking if the score has reached a certain value:
public void CheckScore()
{
...
// Your other logic to increment the score.
...
if (_score >= 10) // Check if the score has reached a certain value.
{
MessageBox.Show("You reached 10 points! YOU WIN!");
}
}
Bingo! ;)
Ok so your issue is that your only calling your code once - when the form is loaded. You need an update event set up and called regularly with the above code to make it work. Otherwise your code looks quite sound. Look into c# timers to get your update method called.
Hi everyone this is my first question to stackoverflow and sorry for my English. I searched for a week and couldn't find the solution. I am working on a project which uses RFID antenna and tags . A machine reads the tags and produces tag id like bcbc 0000 or abab 1111 ... Every id points a unique product like shirt , panth etc.This program is a product counter. My form application uses this id's matches with the products and counts them. When program gets a shirt id I want to increase "shirt count label" on the form at the reading time. I wrote 2 different programs and both didn't update the label.
my codes :
System.Timers.Timer aTimer = new System.Timers.Timer();
aTimer.Interval = 2000;
aTimer.Start();
aTimer.Elapsed += new ElapsedEventHandler(OnTimedEvent);
reading part is below;
reader.Connect(SolutionConstants.ReaderHostname);
Settings settings = reader.QueryDefaultSettings();
settings.Report.IncludeFastId = true;
settings.Report.IncludeAntennaPortNumber = true; // WS
settings.Antennas.GetAntenna(1).MaxTransmitPower = true;
settings.Antennas.GetAntenna(1).MaxRxSensitivity = true;
settings.Antennas.GetAntenna(2).MaxTransmitPower = true;
settings.Antennas.GetAntenna(2).MaxRxSensitivity = true;
...... and other settings here....
// Apply the newly modified settings.
reader.ApplySettings(settings);
// Assign the TagsReported event handler.
// This specifies which method to call
// when tags reports are available.
reader.TagsReported += OnTagsReported;
// Start reading.
reader.Start();
in OntagsReported() function i do some controls and the important part is
tagList.Add(tag.Epc.ToString()); // adds tags to tagList.
timer function ;
private void OnTimedEvent(object source, ElapsedEventArgs e)
{
for (int i = 0; i < tagList.Count; i++)
{
if (!usedTags.Contains(tagList[i]))
{
//MessageBox.Show("");
label1.Text = "Text Updated.";
//productCounter(tagList);
usedTags.Add(tagList[i]);
}
}
}
Everything is working . Program goes last if control. If I write there a messageBox it shows that but on the next line label does not change. Thanks for help :)
System.Windows.Forms.Timer instead of System.Timers.Timer could help you.
System.Timers.Timer fires event in the non-UI thread,
so you should not access UI controls directly in the event handlers.
Seems like you need to marshal the call to the UI thread.
label1.BeginInvoke(new Action(() => label1.Text = "Text Updated"));
Is there an object that will event at a given DateTime or DateTimeOffset? I am using a Timer to do this operation now but it requires a bit of calculation on my part, was just thinking there might already be something in place.
I don't see how you have to do any calculation:
public void StartTimer(DateTime target) {
double msec = (target - DateTime.Now).TotalMilliseconds;
if (msec <= 0 || msec > int.MaxValue) throw new ArgumentOutOfRangeException();
timer1.Interval = (int)msec;
timer1.Enabled = true;
}
I like:
System.Timers.Timer _WaitForScheduledTime;
_WaitForScheduledTime = new System.Timers.Timer();
_WaitForScheduledTime.Elapsed += new ElapsedEventHandler(WaitForScheduledTime_OnElapsed);
_WaitForScheduledTime.Interval = _ListOfJobs.IntervalUntilFirstJobIsToRun().TotalMilliseconds;
_WaitForScheduledTime.Start();
...
private void WaitForScheduledTime_OnElapsed(object source, EventArgs e)
{
log.Debug("Ready to run at least one job");
// restart the timer
_WaitForScheduledTime.Interval = _ListOfJobs.IntervalUntilFirstJobIsToRun().TotalMilliseconds;
_WaitForScheduledTime.Start();
}
If you are using ASP.NET you may be able to add an empty object into the Cache with a declared ExpirationDate then handle the CacheItemRemovedCallback. Just a thought, don't know if it will work for you.
If you not using ASP.NET you still may be able to use this trick with another caching framework such as the Enterprise Library Caching Block
Not that I know of. I rolled my own class to do that.