Label text value does not change after executing an elapsed event callback - c#

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

Related

Error message "Cannot evaluate expression because the current thread is in a stack overflow state"

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.

C# Thread not changing the text box values the second time

I am creating an application that involves using threads. Everything works until I click the button for the second time. Nothing happens on the second time the button is clicked. Its like the first time all the stuff loads and then just locks the values of the text boxes. The stuff in red is just private links that cannot be shown. Its not the links because they work just fine the first time. They just won't work the second time. I hope what I just said wasn't too confusing.
name1, name2, name3 are all downloaded when the form is created, they're just bound to the textboxes when you press the button the first time.
_name1(), _name2(), _name3() methods are just object instantiations and have no side effects of any kind (put differently, they don't do anything).
And all the threading stuff is just fluff - you're calling methods that don't do anything and then aborting the threads (thereby aborting something that isn't doing anything anyway). This has zero effect on the execution in any way as the code is currently written, even when executed the first time.
The simple, synchronous fix for your code will look like this:
private void Button_Click(object sender, EventArgs e)
{
using (WebClient client = new WebClient())
{
textBox1.Text = client.DownloadString("<your URL here>");
textBox2.Text = client.DownloadString("<your URL here>");
textBox3.Text = client.DownloadString("<your URL here>");
}
}
Seeing as you're using threads, your goal is obviously non-blocking, asynchronous execution. The easiest way to achieve it while preserving the sequencing of operations is with async/await:
private async void Button_Click(object sender, EventArgs e)
{
// Disabling the button ensures that it's not pressed
// again while the first request is still in flight.
materialRaisedButton1.Enabled = false;
try
{
using (WebClient client = new WebClient())
{
// Execute async downloads in parallel:
Task<string>[] parallelDownloads = new[] {
client.DownloadStringTaskAsync("<your URL here>"),
client.DownloadStringTaskAsync("<your URL here>"),
client.DownloadStringTaskAsync("<your URL here>")
};
// Collect results.
string[] results = await Task.WhenAll(parallelDownloads);
// Update all textboxes at the same time.
textBox1.Text = results[0];
textBox2.Text = results[1];
textBox3.Text = results[2];
}
}
finally
{
materialRaisedButton1.Enabled = true;
}
}

c# form application label does not update

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"));

How to define a timers interval from a textbox in C#

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;
}

How to instantly change label text during a method at runtime?

I've searched through stackoverflow but cannot find the answer. I don't know if I could make this question clearly. I'm not an English-speaking person anyway =.=
I'm using c# and visual studio 2010 to develop.
I'm making a Form for user to login, I would like this form test sql server connection during load event.
It seems easy, the code is:
private void testDBconnection()
{
label3.Text = "Connecting to Database Server......";
SqlServerConnection ssc = new SqlServerConnection();
bool conOK = ssc.isConnectable(ssc.makeConnectionString(
SqlServerConnParamters.SqlServerIPAddress,
SqlServerConnParamters.AccountValidationDatabaseName,
SqlServerConnParamters.SqlServerUserName,
SqlServerConnParamters.SqlServerPassword,
5));
if (conOK)
{
label3.Text = "";
}
else
{
label3.Text = "Database connection failed";
button1.Enabled = false;
}
}
I put this method in Form_Load event.
But in runtime, this process start even before this form shows. And the validation could last for 15 seconds by default(I set it to 5 but it also takes time). If the connection has some problem, it will display like the programe failed to open, but it will shown after it failed to connect to database.
My intention is tell the user by Label3 displaying "Connecting to Database Server......", and tell user if connection failed.
I was trying to find Form Event like "Loaded_Complete", or "Loaded"(I found Form_Closed though), but I couldn't.
I guess it has something to do with thread, programe sleeping, or else. I hope someone could help me on this. Thanks a lot guys!
I would use a BackgroundWorker this way. That will defer the database check operation, and the form load will not be locked by it.
label3.Text = "Connecting...";
button1.Enabled = false;
var bkw = new BackgroundWorker();
bkw.DoWork += (s, ev) =>
{
SqlServerConnection ssc = new SqlServerConnection();
ev.Result = ssc.isConnectable(ssc.makeConnectionString(
SqlServerConnParamters.SqlServerIPAddress,
SqlServerConnParamters.AccountValidationDatabaseName,
SqlServerConnParamters.SqlServerUserName,
SqlServerConnParamters.SqlServerPassword, 5));
};
bkw.RunWorkerCompleted += (s, ev) =>
{
if ((bool)ev.Result == true)
{
label3.Text = "Connected";
button1.Enabled = true;
}
else
{
label3.Text = "Database connection failed";
}
bkw.Dispose();
};
bkw.RunWorkerAsync();
However, this would require some exception handling. If an exception occurs in the DoWork event, then you can check in the RunWorkerCompleted event wether ev.Error is null or not (it contains the exception) and react accordingly.
Use timer.
In form load event start the timer(set interval to 2 sec or what ever you want). As timer ticks call your connection method. At the starting of your testDBconnection() method, stop the timer and dispose it because you don't need it any more.
You should not be using the Form_Load event to fire events when a form loads, you should override the OnLoad() method instead, that way you control when the code gets fired (it's possible for multiple subscribers to be listening to Form_Load and you don't know what order they will run in).
The quickest and dirtiest way of getting the screen to refresh is to Add
Application.DoEvents();
After changing the label, this forces the screen to update. In general though this is bad practice and the background thread above would be a better solution long term.

Categories

Resources