Solved:
You guys are the best!
I took al the content of goyouidiot_Click and made it into a method called displayResult, and then:
private void t1_TextChanged(object sender, EventArgs e)
{
displayResult();
}
How didn't i thought of that before? lol, thx
here is original messege:
No lone ago i built a little software
that calculates an averege of 15
numbers. The code starts to run when
the buttun is clicked, but i want to
put this code in an infinate loop that
starts to run with program, so the
answer will be auto updated. this is
my code:
private void goyouidiot_Click(object sender,
EventArgs e)
{
.
.
.
.
}
and those who havn't understood:
I have 15 text-boxs, and I want
the method to run when the text boxs'
content changes.
Rather than make an infinite loop (which will cause the application to hang unless it's on a background thread - a much bigger can of worms) you should just respond to change events.
If your numbers are being updated in text boxes, just bind the TextChanged events of each of them to your goyouidiot_Click method - which you should then rename.
Edit
As Eric points out in his answer, the reason these events work is because there is in fact an infinite loop in the background to listen for changes - the Windows message pump. This loop is started when you call the Run method on your application.
Your intuition that an infinite loop must be involved is correct. But you don't want to write that loop yourself; the runtime library has already written it for you. What you want to read up on is event-driven programming. Find a good introduction, like, say:
http://www.c-sharpcorner.com/UploadFile/sksaha/EventsinNet11152005043514AM/EventsinNet.aspx
The way event-driven programming works behind the scenes is that there is an infinite loop of code that monitors the state of a queue of messages coming in from the operating system. The messages are representing things like mouse clicks and typing. The infinite loop code then turns those messages into event firings. You can listen to those event firings and run code when particular events happen.
Putting it in a infinite loop could starve the system of CPU power, meaning you will need to introduce a pause (Thread.Sleep).
If you use a pause, you may as well use a Timer object - there is a form's based Timer or a thread based Timer (System.Windows.Forms, or System.Threading / System.Timers);
I would personally suggest using a timer to tick at a desired interval.
A thread timer uses delegates / thread pool whereas the forms based timer places messages on the message pump - both are not guaranteed to be accurate to their intervals due to the overhead in the way in which a tick is created.
If I understand correctly (you want to update something every 15 minutes in your Winform application), then it is better to use the Timer class, which will run your code periodically.
EDIT: If you want to perform some calculations when a text is changed in one of the text boxes, you should do it in an event handler for the TextChanged event of these text boxes (you want to assign the same handler to every text box)
Related
I have a problem that I have found many similar problems related to multi threading, but noone linked to me specific problem.
I have a method that does something, but when the method has been called, I don't want it to return untill a button is clicked.
So basically, at the end of the method, I would like it to stay put and wait for the Button_Click event to finish, and then the event should in some way "tell" the method to continue.
Currently I have done this by adding a loop at the end of the method like this:
while(someVariable){
Thread.Sleep(10);
Application.DoEvents();
}
Then the Button_Click event set someVariable to be false, and then the loop stops.
Of course, this looks very "iffy", and having this loop run every 10 milliseconds seems like a gigantic waste.
Are there any way of doing this properly? Since the method in question runs on the same thread as the rest of the application, it's also important that halting the method does not block the tread for other activities.
The reason I need this is because when the method is called from somewhere else, this method will draw up some components (including two buttons). Then the user clicks one of them, and then the method will return a different value depending on which button was clicked, and the program calling it can't continue untill it knows which button was clicked. So my program will look like this.
....
if( someMethod() == ButtonA ){
//do the proper action if button 1 is clicked
}else{
//do the proper action if button 2 is clicked
}
I hope this was not to confusing.
Assuming this is in the UI thread, you absolutely should not do this. You say "it's important that halting the method does not block the thread for other activities" - that basically means you need to find a different design. If the UI thread is "staying put and waiting for the Button_Click event to finish" then it can't be doing anything else without using the hack of Application.DoEvents().
Instead, you should make a call back to the original caller when the event occurs. Either expose an event that the caller can subscribe to, and raise that event when the button click finishes, or get the caller to pass in a delegate to call appropriately. (They're equivalent really, just different ways of propagating the callback.)
That's the way WinForms (and other rich client UIs) are designed to work - on an event-based model, basically.
Use AutoResetEvent, see sample and documentation at http://msdn.microsoft.com/en-us/library/58195swd.aspx
Your main thread does a WaitOne() on the event and in you Button.Click event, you Set() the event.
I have a C# windows forms application. The way I currently have it set up, when Form1_Load() runs it checks for recovered unsaved data and if it finds some it prompts the user if they want to open that data. When the program runs it works alright but the message box is shown right away and the main program form (Form1) does not show until after the user clicks yes or no. I would like the Form1 to pop up first and then the message box prompt.
Now to get around this problem before I have created a timer in my Form, started the timer in the Form1_Load() method, and then performed the check and user prompt in the first Timer Tick Event. This technique solves the problem but is seems like there might be a better way.
Do you guys have any better ideas?
Edit: I think I have also used a background worker to do something similar. It just seems kinda goofy to go through all the trouble of invoking the method to back to the form thread and all that crap just to have it delayed a couple milliseconds!
I would use Form1_Shown()
Use the Shown event. It seems to suit what you need, and will only display the first time the form is shown.
Form f1 = new Form();
f1.Shown += new EventHandler(f1_Shown);
public void f1_Shown(object sender, EventArgs e)
{
// Show dialog in here
}
Try the "Shown" event:
Form.Show Event
Using a Windows.Forms.Timer is a good, stable, well-known, and easily understood technique for doing what you want. I would avoid any other timer objects.
The form's Shown event works well.
Overload / override the Show method. (My preferred technique for greater control.) In this method, I would do the checking needed. When ready, I would call the base.Show method, then do any other processing, such as message boxes, prompts, logging, or whatever.
My C# WinForms UI has some parameters that the user can adjust using sliders. Many parts of the UI can interactively update based on the slider values. However, some parts require a longer calculation that requires some overhead to set up. I would like to only initiate this update process once the user has stopped moving the sliders for, say, 2 seconds. What's the best way to do this?
The Reactive Framework would be perfect for that. If you have C# 3.5, you could use it.
Observable.FromEvent<ScrollEventArgs>(vScrollBar1, "Scroll")
.Throttle(TimeSpan.FromSeconds(2)) // Wait for two second alter all Scroll event ended
.ObserveOnWindowsForms() // Make the lambda expression run on the UI thread
.Subscribe(
e =>
{
// Update your stuff
labelControl1.Text = e.EventArgs.NewValue.ToString();
});
You can get rid of the ObserveOnWindowsForms call if you don't want to make your UI to hang while running the lamda, but make sure that you properly access your UI component to avoid cross-threading exception.
You could use a Timer control that resets the UI if any anything has changes after 2 seconds.
The timer would also check a variable that is flagged after every change, so only when the flag has not changes and timer times out, the UI is upated.
I would have a private instance member referencing a thread timer. When the timer hits 2 seconds, the event containing the calculations would fire. All sliders would have an change listener that would set the timer to 0 and start the timer.
You need to use this timer: System.Windows.Forms.Timer. Why? It executes on the UI thread meaning you don't have to use InvokeRequired or BeginInvoke to execute your UI updating code on the UI thread.
I have a Winforms App (.NET 3.X) That runs a method in a class to process some data. The method periodically raises a StatusUpdate event with a count of the number of items processed. I have a ToolStripStatuslabel on the Form that i would like to update with the count. The problem is that status label never updates with this count until the process is complete. Below is the code from the status update event handler
toolStripStatusLabel.Text = e.Count.ToString();
statusStrip.Refresh();
I think the problem is that the Refresh event is not firing because the processing method is being called from within a Button press event. I think there is a way to force the Refresh to process but I do not remember what it is.
My only other solution is to execute the processing in it's own thread.
Found the answer in another thread:
Call Application.DoEvents() after setting the label, but you should do all the work in a separate thread instead, so the user may close the window.
This is the command that I was thinking of...
Have you tried calling refresh on the label itself ?
toolStripStatusLabel.Refresh();
I have a datetimepicker in C#. When I click on it, it expands to show a monthly calendar, when I click the left arrow to go back a month, it changes the value and calls my event. The event includes too much code to include here but it calls several functions needless to say.
The problem I'm having is that when I click that left arrow it gets stuck in some sort of loop and keeps descending through the months and I can't stop it. One of the functions that is being called contains a Application.DoEvents() and if I comment that out it doesn't get stuck in the loop, but I need that command to update another section of the interface. Any idea why this is happening?
I can duplicate it sometimes with this code, sometimes it just does it a couple times, sometimes it gets stuck in the loop.
private void DateTimePickerValueChangedEvent(object sender, EventArgs e)
{
afunction();
}
private void afunction()
{
listView1.Clear();
panel1.Visible = true;
Application.DoEvents();
}
I also have the same problem. In my case, instead of calling DoEvents I'm updating a Crystal Report view. The only workaround I found is to update my view upon the CloseUp event instead of ValueChanged or TextChanged.
Scott, how did you finally corrected your problem ?
The DateTimePicker ValueChanged event is buggy. Per Microsoft Windows Forms Team on this page https://connect.microsoft.com/VisualStudio/feedback/details/1290685/debugging-datetimepicker-event-hangs-vs:
"The DateTimePicker control installs a mouse hook as part of its functionality, but when the debugger has the WinForms application stopped on a breakpoint, it allows the possibility of a deadlock if VS happens to get a mouse message. For now, the deadlock is unfortunately a consequence of the DateTimePicker's design. The mouse hook is installed when the drop down is clicked to display the calendar. This means that breakpoints should not be sent in any event handlers which would be called while the calendar is active. We are currently investigating whether it is possible to address this issue and we will update this thread with further information if we are able to make a fix available."
Without seeing any of the code, try these steps:
Comment out the entire event handler
to see how fast it runs with nothing
attached to it.
Uncomment lines one at a time to see
which ones are causing the most
problems.
Analyze those method calls.
...
Profit!
You could try a couple of things. Get rid of the DoEvents inside of the ChangedEvent.
Call the doevents inside of a seperate function after maybe a period of time (thread.sleep() ?).
I know doevents does cause issues but I rarely use it.
event procedure ValueChanged :
set parameter in sender.tag
enableTimer and execute parameter using sender.tag
example:
private void DateTimePicker_ValueChanged(object sender, EventArgs e)
{
DateTimePicker ThisSender = (DateTimePicker)sender;
Timer.Tag = ThisSender.Name.ToString() + "=" + ThisSender.Value;
Timer.Enabled = true;
}