I'll be short and to the point. I basically need a way I can take a timer, check when the timer is up and execute something at the end of it, then loop it. For example (this code isn't serious, just example code) :
Timer1.start();
If (timer1.TimeRanOut) {
Timer2.start()
}
Or some other way to pause the timer without the GUI freezing up (I'll be running some things at a fast pace and freezing would get in the way). I'll be making this more complex by looping the entire process, like :
if (Checkbox1.checked == true; )
{
Timer1.start();
Next If (timer1.TimeRanOut) {
Timer2.start()
}
Next If (timer2.TimeRanOut) {
Timer3.start()
}
And so on. Any solutions?
I would suggset working with Tasks. you set up a task to do something (it can just wait for X seconds, than it is a timer) than you set continueWith to assign a new task to run when the first one is finshed.
You can read more about this here:
http://msdn.microsoft.com/en-us/library/dd537612.aspx
And by the way, you really should not run heavy calculations on the UI thread itself.
If you decide to use tasks - that would be fine. Otherwise , you need to create background thread and do the work there.
Edit:
After some clarification from the OP , I will try to explain the basics or working with UI and background threads:
When you run a winforms/WPF application, all of the user interface events are handled in a single thread - the UI thread. it goes over all of the events and processes them.
If long calculation occupy this thread, the UI will become "stuck" and o responsive. see:
UI freezes on heavy calculation
That is why, any long calculations should be done on another thread, in the background.
In the above post's answer there is an example on how to do this.
You could use the System.Threading.Timer. You would then make use of its single shot capability (see Change method). Such you may chain several timers.
The callback of this timer runs on the thread pool so your UI doesn't freeze.
Related
I Have a WPF multithread application, and each thread updates some variables of objects binding to the xaml gui.
If I Use a normal thread or a threadpool it works fine. Each object is being updated at real time in the GUI when the object variables is changed by the treads.
I want to use Parallel.ForEach because it stops the execution util all threads are finished. This is important to me for block the interface (because the use should wait), and for can show a finished message. The bad thing is that with Parallel.Foreach is not being updated in real time, only when all threads are finished.
This way works, but It only updates the Gui at the end.
Parallel.ForEach(Computers, new ParallelOptions { MaxDegreeOfParallelism = 1}, computer => { PingTemp(computer); });
This way works, but It doesn't wait to the end of the ThreadPool.
Task.Factory.StartNew(() => Parallel.ForEach<Computer>(Computers, new ParallelOptions { MaxDegreeOfParallelism = 1 }, computer => PingTemp(computer)));
What approach do you recommend when the GUI is updated in realtime and wait the execution of threadpool before continue.
Do NOT do that in the same thread. If you need the user to wait, then use a mechanism where you LOGICALLY stop interaction at the UI (turn if ff, put a transparent label with a working animation on top of the window) and do things outside the loop. The whole UI interaction is blocked as long as your thread blocks.
YOu do NOT get ANY updates in the UI while the UI thread is blocking. So, that already kills what you want. But more important - you really make bad things. ALWAYS keep the UI free.
My old rule is 0.1/1. Everything longer than 0.1 seconds MUST go into a non-ui thread, anything longer than 1 second MUST disable the UI and show a working animation, preferably one that shows progress if feasible by any mreans.
I use a GUI framework that handles that automatically via bound method signatures (telling the UI this method call is async, then the routine is automatically called in a separate thread).
I have a program that starts constantly juggles between 3 separate timers.
The main thread of my application has a while loop which constantly checks if a global variable has been set to true and if it has, it will stop one timer and launch two other ones - one continuously, another to stop it automatically if it isn't commanded to stop for whatever reason.
This while loop has a condition of (1==1) so that it runs forever.
In the task manager (XP) I see that my program is using up 50% of cpu on a more or less idle system.
Is there a way to decrease that number by decreasing the speed of the while loop or something?
Thanks.
Is there a way to decrease that number by decreasing the speed of the while loop or something?
Just stop doing a busy loop. There are better ways of coordinating events between threads. Consider using Monitor.Wait/Pulse, or AutoResetEvent / ManualResetEvent. Basically, the thread that sets the global variable should signal that it's done so. Alternatively, if your main thread wouldn't be doing anything else, why not add a normal C# event so that whenever the variable is changed, the event is raised and the appropriate action can be taken?
Your program performs busy waiting, which is a bad practice. You should change your logic so that instead of looping, you block on some kind of synchronization primitive (also known as wait handle).
Blocking on a wait handle is not an option for the UI thread, so you would have to create three threads in total and implement the scheme like this:
The UI thread does not concern itself at all with what other threads to. No looping, no sleeping, no blocking.
The new "controller" thread would start the existing "worker" thread and then immediately block (e.g. on an event that is not signaled). It will remain in this state, without consuming CPU, until the event is signaled (i.e. the "worker" completes).
The "worker" thread would run its course and then signal the event.
Is there a way to decrease that number by decreasing the speed of the while loop or something?
Yes, you could insert a call to Thread.Sleep(n). With a granularity of ~20 ms.
But the far better option would be using a Waithandle.
Your main thread would Wait on the handle and the end of the timer code would signal it to wake up.
You need to sleep the threat for a given number of ms. Look at the Thread.sleep() function and place it within your while loop.
The easiest way to slow down a loop like this is to just add a System.Threading.Thread.Sleep(100); For every iteration the process will sleep for 100 ms and it will not use 50% cpu anymore.
You can use Threads instead of Timer it costlier than Thread. Or Please check the thread state of your time which stopped before start another. You can improve performance by cutting down your code logic.
Hope this will helps you. :)
While the answers here aren't wrong per-say, They don't really address a lot of issues with doing while(true) loops which is what while(1==1) is.
First of, even if the loop is running the entire time your application is in use, you will want to shit it down at some point, say when the user exits your application, because if you have a thread with a constant loop, even if the user closes the UI window, the process will remain until the thread exits (which is never in a while true loop) or until the user becomes wise and closes it from the task manager.
You COULD solve this by putting a true conditional in the while conditional check that references a accessible property outside the loop.
Example:
private bool RequestExit = false;
private Thread MyLoopThread;
private void MyLoop()
{
while (!RequestExit)
{
//Do stuff!
Sleep(1);
}
}
public void StartLoop()
{
RequestExit = false;
MyLoopThread = new Thread(MyLoop);
MyLoopThread.Start();
}
public void StopLoop()
{
RequestExit = true;
}
That is the bare-bones and doesn't even get into avoiding double launches or double shutdown events.
A much cleaner way would be to set an arbitrary interval that you want to pool at, 10ms or so should do just fine for pretty much any real time event, and trigger an method to fire at that interval.
private Timer DoStuffTimer;
private void DoStuffMethod(object obj = null)
{
//Do stuff!
}
public void StartLoop()
{
DoStuffTimer = new Timer(DoStuffMethod,null,10,10);
}
public void StopLoop()
{
DoStuffTimer.Dispose();
}
How do you implement busy waiting in a not total inefficient way? I am facing the issue that I can load the data of my model only in a pull manner, which means I have to invoke getXYZ() methods in a continuous way.
This has to happen not fast enough for user interaction, but fast enought, that when a state in the GUI is changed, the model can be noticed and the new state is received by the getXYZ() methods.
My approach simply be:
while (c.hasChanged()) {
Thread.sleep(500);
}
updateData();
Are there better mechanisms?
Your problem seems to be solvable with Threading.
In WPF you can do:
Thread t = new Thread((ThreadStart)delegate() {
while (true) {
Thread.sleep(500);
if (c.hasChanged())
Dispatcher.Invoke((Action)delegate() {updateData();});
}
}).Start();
In WinForms
Thread t = new Thread((ThreadStart)delegate() {
while (true) {
Thread.sleep(500);
// this must derive from Control
if (c.hasChanged())
this.Invoke((Action)delegate() {updateData();});
}
}).Start();
There may be missing parameters to Invoke (which is needed to execute the code on the calling UI thread) but I'm writing this from my brain so no intellisense at disposal :D
In .NET 4 you can use TaskFactory.StartNew instead of spawning a thread by yourself.
In .Net <= 4, you could use the TreadPool for the thread.
However I recall you need this to be run at once because you expect it to be there checking as soon as possible and the thread pool won't assure you that (it could be already full, but not very likely:-).
Just don't do silly things like spawning more of them in a loop!
And inside the thread you should put a check like
while (!Closing)
so that the thread can finish when you need it without having to resort to bad things like t.Abort();
An when exiting put the Closing to true and do a t.Join() to close the checker thread.
EDIT:
I forgot to say that the Closing should be a bool property or a VOLATILE boolean, not a simple boolean, because you won't be ensured that the thread could ever finish (well it would in case you are closing the application, but it is good practice to make them finish by your will). the volatile keyword is intended to prevent the (pseudo)compiler from applying any optimizations on the code that assume values of variables cannot change
It's not clear from your post exactly what you are trying to do, but it sounds like you should put your model/service calls on a separate thread (via Background worker or async delegate) and use a callback from the model/service call to notify the UI when it's done. Your UI thread can then do busy things, like show a progress bar, but not become unresponsive.
If you are polling from a GUI, use a (WinForms) Timer.
If this is some kind of background process, your Sleep() may be the lesser evil.
Explicit busy waiting is evil and must be avoided whenever possible.
If you cannot avoid it, then build your application using the Observer design pattern and register the interested objects to an object which performs the polling, backed by a thread.
That way you have a clean design, confining the ugly stuff in just one place.
I have window with button which triggers lengthy processing. I put processing in a separate thread, but -- to my surprise -- it makes GUI frozen anyway. No control is refreshed, I cannot even move the window.
So the question is how to start the thread, so it won't interfere with GUI, i.e. so the GUI would always be up to date (while processing I change the data, and GUI displays some pieces of it)?
That is how I start thread currectly:
var thread = new Thread(doLearn);
thread.IsBackground = true;
thread.Start();
Edit 1
Jon:
I don't use any locks at all
No Join calling
The UI thread is left alone -- it simply sits there
The processing is a big loop with math operations, not even allocating memory, on UI side I have controls with binding (WPF) to data, like the number of current iteration of the main loop. It should be refreshed each time the main loop "ticks". The counter of the loop is a property which triggers OnPropertyChanged with each change (classic WPF binding).
Edit 2 -- Almost there!
Ok, so Jon hit the nail at the head (who is surprises? ;-D) -- thank you! The problem comes from changing the Counter. When I used instead the Counter, local counter the GUI was refreshed -- I mean I could move windows, but... I couldn't see display of the Counter.
What I have here -- a WPF GUI, with such data-binding
<TextBlock Text="{Binding Path=Counter"/>
and I have Counter property of course which on each change sends event PropertyChanged. One of the listeners is for sure GUI.
So, Jon answer is valid "the answer", but from good design POV not exactly, because if GUI part has to pull up the info about Counter and update the display every (let's say) 3 seconds, why would anyone use data binding? For me such approach invalidates data binding idea.
I could, theoretically, pass to the processing thread the GUI dispatcher, and do all the sending in GUI thread, and it could work (I didn't try it) but it would mean tight coupling of non-GUI part and GUI part.
So far, I have no idea how to do it "right" way. The best guess so far is to create TimerDispatcher but not at GUI side but inside the processing library, and update Counter value immediately but do all the sending from time to time (I didn't try it yet though).
Small remark: I have more properties binded actually, like IsRunning, which is changed at the beginning and at the end of processing. And those changes DO affect the display correctly -- but the Counter change triggers around 3000 notifications in 3-4 seconds. So it looks like jamming problem. I did another test -- I killed the data binding partially, so notifications were sent, but GUI was not "receiving" them -- but was listening to them. In such case the GUI was also frozen.
So, I am still listening to all advices -- thank you advance for sharing.
Edit 3
The saga continues here:
How to do the processing and keep GUI refreshed using databinding?
It should be fine as it is. Things which may be freezing your UI:
Are you locking within the UI thread, and locking on the same lock in your other thread?
Are you calling Join on the thread from your UI thread?
Are you doing some other heavy work in the UI thread?
If you could come up with a short but complete program which shows the problem, I'm sure we could help to fix it... but it certainly should be okay.
EDIT: Okay, now you've added this:
The counter of the loop is a property which triggers OnPropertyChanged with each change (classic WPF binding).
So you're updating the property from the non-UI thread? I would expect that to cause problems, because it will trigger UI changes from the wrong thread.
I suggest you take an approach such as:
Periodically update the counter via Dispatcher.BeginInvoke
Have the "UI counter" and the "worker counter" - and copy the value from the "worker counter" to the "UI counter" in the UI thread via a DispatcherTimer, essentially polling it.
There are numerous methods to run functions off the UI thread, but the easiest and generally most suitable is to look at the BackgroundWorker component. Many decent tutorials can be found. For example, here.
I put processing in a separate
thread, but -- to my surprise -- it
makes GUI frozen anyway.
I really hate to tell you, but then you did NOT put it into a separate thread. That simlpe.
There was a poster here that had a similar issue some time ago and through a mistake in his invoking code he basically had all processing before the thread started, with the thread jsut returning the result.
I faced the same situation, and solved it by two ways...
Use the thread in other class and invoke it in ur main application by creating Thread, either in its constructor OR in any method.
if u want do the it in same class, then create a Thread that call your function, and that function should invoke the Delegate.
See the examples:
public partial class Form1 : Form
{
private delegate void TickerDelegate();
TickerDelegate tickerDelegate1;
public Form1()
{
InitializeComponent();
}
//first solution
// This button event call other class having Thread
private void button1_Click(object sender, EventArgs e)
{
f = new FormFileUpdate("Auto File Updater", this);
f.Visible = true;
this.Visible = false;
}
// Second Solution
private void BtnWatch_Click(object sender, EventArgs e)
{
tickerDelegate1 = new TickerDelegate(SetLeftTicker);
Thread th = new Thread(new ThreadStart(DigitalTimer));
th.IsBackground = true;
th.Start();
}
private void SetLeftTicker()
{
label2.Text=DateTime.Now.ToLongTimeString();
}
public void DigitalTimer()
{
while (true)
{
label2.BeginInvoke(tickerDelegate1, new object[] {});
Thread.Sleep(1000);
}
}
}
I have a WinForm drawing a chart from available data.
I programmed it so that every 1 secong the Winform.Timer.Tick event calls a function that:
will dequeue all data available
will add new points on the chart
Right now data to be plotted is really huge and it takes a lot of time to be executed so to update my form. Also Winform.Timer.Tick relies on WM_TIMER , so it executes in the same thread of the Form.
Theses 2 things are making my form very UNresponsive.
What can I do to solve this issue?
I thought the following:
moving away from usage of Winform.Timer and start using a System.Threading.Timer
use the IsInvokeRequired pattern so I will rely on the .NET ThreadPool.
Since I have lots of data, is this a good idea?
I have fear that at some point also the ThreadPool will be too long or too big.
Can you give me your suggestion about my issue?
Thank you very much!
AFG
It is a good idea to move the fetching of the data to a Thread. You can use a BackgroundWorker that gets the data in an endless loop and
use the UpdateProgress event to update the chart. This takes care of the InvokeRequired business
Use a Sleep(remainingTime) inside the loop to get a desired frequency.
It is quite unlikely you'll be ahead by using a background timer. Your chart control almost certainly requires it to be updated from the same thread is was created on. Any kind of control that has a visible appearance does. Which requires you to use Control.BeginInvoke in the Elapsed event handler so that the update code runs on the UI thread. Dequeueing data isn't likely to be expensive, you will have actually have made it slower by invoking. And still not have taken the pressure off the UI thread.
You'll also have a potentially serious throttling problem, the timer will keep on ticking and pump data, even if the UI thread can't keep up. That will eventually crash your program with OOM.
Consider instead to make the code that updates the chart smarter. A chart can only display details of the data if such details are at least a pixel wide. Realistically, it can only display 2000 pixels with useful information. That's not much, updating 2000 data points shouldn't cause any trouble.
I would go with a System.Timers.Timer over a BackgroudWorker in an endless loop.
The BackgroundWorker is executed from a ThreadPool and is not meant to run for the lifetime of your application.
Motivation for System.Timers.Timer:
Each elapsed event is executed from a ThreadPool, won't hang your UI thread.
Using a combination of locks and enabling/disabling the timer we can get the same frequency as if we did a Thread.Sleep(xxx) in an endless loop.
Cleaner and more obvious as to what you are trying to achieve
Here's my suggestion:
Disabling the timer at the beginning of the method, then re-enabling it again at the end, will cater for the case where the amount of work done in the elapsed event takes longer than the timer interval. This also ensures the timer between updates is consistent. I've added a lock for extra precaution.
I used an anonymous method to update the UI thread, but you can abviously do that however you want, as long as you remember to Invoke, it's also a good idea to check the InvokeRequired property
private readonly object chartUpdatingLock = new object();
private void UpdateChartTimerElapsed(object sender, ElapsedEventArgs e)
{
// Try and get a lock, this will cater for the case where two or more events fire
// in quick succession.
if (Monitor.TryEnter(chartUpdatingLock)
{
this.updateChartTimer.Enabled = false;
try
{
// Dequeuing and whatever other work here..
// Invoke the UI thread to update the control
this.myChartControl.Invoke(new MethodInvoker(delegate
{
// Do you UI work here
}));
}
finally
{
this.updateChartTimer.Enabled = true;
Monitor.Exit(chartUpdatingLock);
}
}
}