I have the issue that using one or two timers on form1 and at the same time showing form2 makes form2 lag everytime the timer refreshs with its interval. If I try to move the Form2 while Form1 is running with its timers it stocks every 500ms and its annoying and makes the program feel slow.
I know I could just use a Backgroundworker but I want to use as less CPU as possible, using a Backgroundworker my Program increases CPU up to 10% (I don't know why, probably because of using a second thread? Is it possible to reduce the CPU Usage?)
Or is there something else, some code I could add to make the Form2 responsible while the Form1 timer is refreshing without Threading or atleast without a Backgroundworker?
Thanks for your help.
Well at the end Im using a threading.timer. :)
Related
I am working on a wpf project...I've faced similar issues in the past,but didn't get the answer to it and that's why i'm asking again :)
My WPF app has 2 windows,one works as a splash screen and the 2nd one is just a basic window with a canvas.The splash screen has a BackGroundWorker.Now,i have this code :
Dim h2 as new Window2
For Each fi As FileInfo In New DirectoryInfo(Application.StartupPath +
"\data\img\em_sml").GetFiles()
h2.canvas.children.add(new Button)
Now, my question is how do i use this code in the backgroundworker in Window1 ?? I tried this :
Dim method as Delegate
Private Sub BgWorker_DoWork(sender As Object, e As DoWorkEventArgs) Handles BgWorker.DoWork
If h2.Dispatcher.CheckAccess Then
For Each fi As FileInfo In New DirectoryInfo(Application.StartupPath +
"\data\img\em_sml").GetFiles()
h2.canvas.children.add(new Button)
Else
h2.Dispatcher.BeginInvoke(DispatcherPriority.Normal, method)
For Each fi As FileInfo In New DirectoryInfo(Application.StartupPath +
"\data\img\em_sml").GetFiles()
h2.canvas.children.add(new Button)
End if
A few things i'ld like to clear here :
• I got the sample code from another SO post(i converted it from c#)
• Dim method as Delegate,i don't really know how to use a delegate function
• The code above returns some exceptions like Parameter name:Method , Value can not be null(I know what this means but as i said,i don't know how i can use the delegate function in such a case)
Any help would be appreciated
The code you're using is trying to invoke to the UI thread via Dispatcher.BeginInvoke(). This is the way to do it in threads, but not in a BackgroundWorker. In a BGW you're supposed to call the ReportProgress() method combined with subscribing to the ProgressChanged event.
However for what you're trying to do, this is not good at all...
For starters: You should NEVER create controls in a background thread! All work related to the UI (User Interface) must always, always, always be done on the UI thread ONLY.
Secondly: There isn't really a good reason for trying to do this in a background thread. The way you're doing it now constantly updates the UI thread, causing it to lag/freeze anyway. What you could do to minimize the lag is to add the buttons in batches, but then as I said before you shouldn't be creating controls in a background thread at all.
Finally: The whole operation of iterating a few files and creating buttons for them really isn't very heavy. Unless you have thousands of files (in which case you should only display them in batches) this will not take that long to perform on the UI thread.
Conclusion: Skip the BackgroundWorker and run your code on the UI thread instead. If you have a really huge amount of files to load, store their paths in a list, only load them in batches and let the user decide when to load the next batch of files.
Can BeginInvoke do the same thing as a BackgroundWorker ? I mean aren't both having the same goal in the end which is doing async operations in a different thread ?
If i have a WPF windows.. and i want to access database using both methods. Is the effect going to be the same ?
You can replace BackgroundWorker with BeginInvoke, but it will take some additional code BackgroundWorker wraps up the management of the background thread in a pretty friendly way.
BeginInvoke can certainly take care of doing work asynchronously. It's a bit lower level, so you have some more flexibility (at the price of having to do more of the work yourself).
I have a method UploadReportNotifier() which is subscribed to an event, which is raised once i have finished uploading data to a database. In UploadReportNotifier() i want to reset some values on my GUI, ie progressbars etc, but i want there to be a time delay between doing this.
Is it possible to create a thread inside UploadReportNotifier() and call thread.Sleep, or is the timer() class more appropriate?
Thanks for your help.
If your goal is to wait a few amount of time after the execution of UploadReportNotifier before updating all your GUI controls, then a timer would be a good solution IMO.
In your UploadReportNotifier method, you can create and start a timer so your "update my GUI" code will be executed after a few time. Don't forget to stop/dispose your timer after your GUI update as you probably don't want it to be executed multiple time.
You could use the System.Windows.Forms.Timer timer class (as you may know, there are multiple timer classes available).
This one is not the most accurate one, but it executes the code in the UI thread, so you won't deal with cross-thread exceptions when modiying your UI.
I see you have found your solution. I just want to mention that in this situation you should always choose timers over Thread + Sleep, which imo is just an ugly hack that should be avoided always.
Timers are great because they are also capable of executing their code on the GUI thread, so you don't need to use Invoke or BeginInvoke. For example System.Windows.Forms.Timer for WinForms or System.Windows.Threading.DispatcherTimer for WPF.
a bit of a juvenile question...
I realise that in a Winforms app, long running code should be executed in its own thread. How does one accomplish this on say, a button click event?
I want to do this in an effort to free up the UI thread so that I can simultaneously overlay the current form with a semi-transparent modal dialog form. I've aleady created the modal dialog form with a neat loading GIF located in the centre that works perfectly on a button click event on its own.
The reason I've chosen this method, is because (1) I want to block any user interaction with the form while the code is being executed, and (2) provide the user with an indication that processing is underway (I dont know how to judge how long a particular piece of code will take to execute, hence opting for an indefinite loading indicator gif).
Also, on the topic of executing code in separate threads...should this not apply to any code, or only specifically to long-running code?
I would really appreciate any help on this matter! thank you!
One of the simplest ways is to use a BackgroundWorker component. Add a BackgroundWorker to your form, add an event handler for the DoWork event, and call the long-running function from there. You can start it in your button click event handler by calling the RunWorkerAsync method on the BackgroundWorker component.
In order to know when the operation is ready, set up a handler for the RunWorkerCompleted event.
private void Button_Click(object sender, EventArgs e)
{
myBackgroundWorker.RunWorkerAsync();
}
private void myBackgroundWorker_DoWork(object sender, DoWorkEventArgs e)
{
// long-running operation here; will execute on separate thread
}
private void myBackgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
// operation is ready
}
I'll answer the second half of your question (as Fredrik has already explained the BackgroundWorker):
No, it does not make sense to move a task to a separate thread unless the task is long running.
Running a task on a separate thread always incurrs extra overheads. It might take more of the UI thread's time to kick off the thread and handle the task completion then it would have to simply do the task in the first place.
Like any programming technique, you have to weigh up the costs and benefits for the particular situation.
I will attempt to answer the second part of your question, based on my own experience.
You will generally only use threads in one of three circumstances:
On operations which will block for noticeable periods of time on system calls (File/Socket IO, etc.)
On long running operations where a loss of UI responsiveness is undesirable.
With multiple long running operations, where exploiting a multi-core environment is desirable.
As Andrew Shepherd says, there are overheads for using Threads.
Threads complicate things dramatically. Never thread for the sake of threading.
In my WinForms application, I need to pop up a little custom dialog that stays on the screen for X amount of seconds and then disappears. So I use a System.Threading.Timer to invoke the _dialog.Close() method once the appropriate amount of time has elapsed. This of course means that I have to do the whole "if InvokeRequired BeginInvoke" dance which isn't really a problem.
What is a problem however is that my main thread might be off doing god knows what by the time the BeginInvoke is called. It might not get around to closing the window for quite a while. I don't need the window to close at a millisecond's notice, but within a second or so is really necessary.
So my question is how does BeginInvoke actually work itself into the main thread and how can I get around this odd limitation?
If your UI thread is busy for many seconds at a time, then:
You won't be able to close a window associated with that UI thread, without peppering your code with Application.DoEvents calls (a bad idea)
Your whole UI will be unresponsive during this time. The user won't be able to move any of the application's windows, and if the user drags other windows over the top of it and off again, you'll end up with an ugly mess while the UI waits to repaint itself.
Certainly use a System.Windows.Forms.Timer instead of a System.Threading.Timer for simplicity, but more urgently, look at fixing your code to avoid having such a busy UI thread.
UPDATE: The conclusion would seem to be that utilising ['BackgroundWorker](http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.aspx) along with a System.Windows.Forms.Timer would be the best approach.
Best to use System.Windows.Forms.Timer for this purpose - this is precisely the sort of application it was designed for. Add one to the pop up form and start it as soon as the form is shown, then hide the form on the Tick event. This solution won't give you any threading issues because the timer runs purely on the UI thread.
Edit: If you want to move the logic outside of your popup form, then I recommend you just create an overload for the Show method within the form code that takes a timespan for its parameter and does the job of setting the Timers's interval and starting it.
Edit 2: If you're main (UI) thread is doing too much work and therefore blocking the message pump and not allowing the timer to fire, then it's the design that's the issue I'm afraid. Your UI thread should never be blocking for more than a fraction of a second. If you need to do serious work, do it in the background using a worker thread. In this case, because you are using WinForms, BackgroundWorker is probably the best option.
Create a dedicated thread and use Application.Run to create and show your form. This will start up a message pump on the second thread which is independent of the main thread. This can then close exactly when you want it, even if the main thread is blocked for any reason.
Invoke and BeginInvoke do get into the main thread by using a window message posted into that thread, waiting for it to be processed. Therefore, if the message pump of the main thread is not processing messages (e.g. busy), it will have to wait. You can mitigate this factor by calling Application.DoEvents() when doing time-consuming operations in the main thread, but that's not really a solution to the problem.
Edit: Sample from some splash screen code (the form requires no special code or logic):
private void ShowSplashInSeparateMessageQueue() {
Thread splash = new Thread(ShowSplashForm);
splash.IsBackground = true;
splash.Start();
}
private void ShowSplashForm() { // runs in a separate thread and message queue
using (SplashForm splashForm = new SplashForm()) {
splashForm.Load += AddDestroyTimer;
Application.Run(splashForm);
}
}
private void AddDestroyTimer(object sender, EventArgs e) {
Form form = (Form)sender;
System.Windows.Forms.Timer timer = new System.Windows.Forms.Timer(form.Container);
timer.Tick += delegate { form.Close(); };
timer.Interval = 5000;
timer.Start();
}
Invoke just places the delegate into the message queue of the thread you want to invoke it on. You could use the Dispatcher class to insert the delegate with a high priority, but there is no gurante that this will meet you timing constraints if the thread is doing a lot of work.
But this might be an indication that you are doing to much work on the user interface thread. Not responding for a second is a pain to a user. So you might think about moving some work out of the user interface thread.