c# winforms sdi application updating multiple progressbars - c#

Happy New Year all,
I am developing a C# Winforms SDI application that relies heavily on background worker threads to carry out long-running database queries. My main dialog box contains a progress label and progress bar; but also a Toolstrip Menu, which contains two ToolStrip Labels and two Toolstrip Progress Bars. I update the progress labels and progress bars via delegates called by event handlers (OnUpdateProgress(object sender UpdateProgressEventArgs e)).
I am seeking your expert opinion on what approach I should use when invoking the UI delegate with regards to trying to achieve a more "generic" and reusable approach.
Thusfar I have considered 2:
(1) When instantiating a worker thread from the main dialog to carry out a background task, pass in a handle to the Label and Progress Bar controls to be updated when the event handler calls back, and
(2) Pass in the name of the Label and Progress Bar to be updated when the event handler is invoked; and use the Form.Find method to retrieve a Control[] of matching controls.
I cannot decide on which of these approaches to use; or indeed if there is a better way of doing this. I believe that method (1) is a little clunky and inelegant; but that method (2) is prone to failure and notwithstanding that the Form.Find method may introduce unreasonable overhead searching for embedded Toolstrip Menu Controls.
I have searched previously asked/answered questions for a solution.
Your advice if much appreciated!

Related

Controls doesn't show if heavy process

I use c# in winform.
Before a very heavy function, I want to show a waiting form to prevent the user. The form opens, but the controls in it are not drawn.
In the following code, waitingForm is a little form, with only a textbox and a progressbar
using (WaitingForm waitingForm = new WaintingForm())
{
waitingForm.Show();
HeavyFunction();
}
I see only two white rectangles, where the controls should appear. Why this happens ?
You can't show the waiting form before the heavy processing and expect the UI to remain responsive. The thread that you're clogging up with HeavyFunction() is the same one that is responsible for drawing forms, controls and maintaining the UI. Use a BackgroundWorker or the ThreadPool to offload the heavy processing to another thread.
EDIT: Also, please consider Ron Beyer's input regarding async/await

Form load interface

In my form_load I have a mysql connection that loads data in a datagrid, when starting my application it will first try to load the mysql database and after its done it will load the form/interface with all the controls.
This leaves the user the impression nothing is happening, how can I first load the form/interface with all the controls and then my mysql database?
I would say, 3 approaches
1 - Separate Splash screen
2 - On-Form "splash screen" - first thing you do on form.load, is Me.Show(), then show a message, something like "Please wait while data is loaded". Progress can be shown to users as well using Application.DoEvents which will refresh your screen.
3 - Background worker thread. Using it, you can actually give user progress updates. That will leave your form completely responsive. http://msdn.microsoft.com/en-us/library/cc221403%28v=vs.95%29.aspx
Move your code to Shown event or OnShown overridden method. this will allow your form shown to user before it loads grid.
You should move your "Database calls" to worker threads as well.
protected override void OnShown(EventArgs e)
{
//Delegate the DB calls to worker threads here
//everything will be smooth then..
base.OnShown(e);
}
There are two ways to approach this situation. You need to pick the approach that best suits your needs.
Approach 1: Create a splash screen. A splash screen is a small window that opens up and usually had product info and a message like "Initializing...". You can see this in a lot of applications, such as Microsoft Office. You can see how to make one by looking at this article.
Approach 2: You will need to make your load data happen in a separate thread then your UI. You will need to load your data in the separate thread and bind it to a list of some sort temporarily, then after its done, bind the list to your Datagrid
Use other thread for loading data from mysql. It's loading form first, but not displaying it until code has finished work.
new Thread(new ThreadStart(LoadDataMethodHere)).Start();
You can use Form Shown event.
Alternatively you can use a different thread to connect to database and show data or use a timer.

Can I freeze my UI rendering while my form loads?

Is there any way I can pause all UI Update commands in Winforms?
Or I have a slight feeling I'm trying to go about this the completely wrong way, so is there another way around my problem: I basically load a saved state of a control, which loads new controls all over it. However I do some of this in the UI thread, and some of the data loading from another thread, which then fills the UI.
So the effect I have when it is loading is that the user can see a few of the controls appearing in one place, then moving to another place on the form, changing values, etc.
I'd like to get a loading screen instead of this and load the controls in the background. It's quite a large application and its not THAT important so redesigning my code isn't really an option.
Can I simply stop all Update() commands on a control while a method is executing?
You can use the SuspendLayout and ResumeLayout methods to wrap the setup of UI in one operation (without the update of the rendering).
Basically (assuming SomeMethod is in the form class):
private void SomeMethod()
{
this.SuspendLayout();
// all UI setup
this.ResumeLayout();
}
it really depends on your form logic, in general you should not overload the Load or Show method with too much things so that the form can be shown and drawn quickly and always look responsive.
in some cases it could help to use the SuspendLayout and ResumeLayout methods, see here:
Control.SuspendLayout Method

WinForms: Looking for an easy way to pop up a 'Processing..' panel

I have a WinForms application that, at some point, will do some calculations that take a couple of seconds. During this time, I disable the controls. Additionally I want to display a popup that kind of 'blocks' the application more visibly.
I tried placing a Panel on top of the Form in order to do so, but there I'm somehow not able to add any text to it. I.e. the Labels and ImageBoxes I put there are somehow not displayed or behind the Panel.
Any suggestions how I could achieve this in a quick and easy way? .. I mean, without redesigning the whole Form.
Your problem with the things not showing up in your additional panel is that everything is happening in the same thread, but your calculations are blocking everything from appearing because they are hogging up the thread. You should look into using a backgroundWorker, which is one of the tools in WinForms. You should throw the function call that performs the calculations into the DoWork method of the backgroundWorker, then the form itself can continue to function during the calculations.
See http://msdn.microsoft.com/en-us/library/cc221403%28v=vs.95%29.aspx for examples
Create a Dialog Box (windows form) to popup during the processing, then you can have the Dialog Box close once your processing is completed.
By using a Dialog Box not a Message Box, you can still have control over closing the window when your processing is done.
You could create a simple UserControl with just a Label and an ImageBox, maybe with public setter for their values. You can add it to your form setting its Visible property to false. Then you can make it visible during your calculations and go back top invisible in the end.

Where to implement BackgroundWorker. Winforms c#

I have created a UserControl using a DevExpress XtraTreeList. Basically in this user control I am using inventory Items. which are more than 30,000. Now when I load the complete table in my typed DataSet it takes almost 6-8 seconds.
The purpose to build the usercontrol is reuseability. So that we can use it in other parts of the application.
Now I am using this UserControl in a Winform, where this usercontrol is place in the left hand side on the form where it will be used as a Menu. The user is suppose to click its desired item by expanding the nodes and when the nodes is selected and then its further details will be fetched and will be displayed in the from. So far so good.
Now the reals issue is that in the same form along with other controls, we have a Devexpress XtraButtonEdit(build using a textbox and a button on the right handside). This buttonEdit is displaying the currently selected Item(from the treeMenu UserControl) code in its textbox, when we are clicking the buttonEdit button then we are loading another form as a model and displaying the same UserControl (XTRATreeList from DevEpress). The only issue is that when I am laoding this new form as a model. The tree again takes time to load which looks bit awkward.
To rectifiy this issue, I am trying to implement the Background worker thread, but bit confused that where should I implement that backgroundWork. In the User Control or in the form.
If I implement that Background worder in the UserControl then how can I access this BackgroundWorker thread and execute it on the main Form where I am using the UserControl on the left hand side as a Menu. Actually what I want is when user clicks the ButtonEdit control and the form loads, it should load like a flash or max in 2 sec....please help.... and execute it.
I hope that ppl will understand my issue.
If somebody finds any difficulty plz let me know....
Regards,
You don't have to "access this BackgroundWorker thread and execute it on the main Form".
A user control could contain its own Bgw. You nee a synchronous method (on the UC) to start it. Then handle the completed (and mayb progress) events inside your UC.
But the data won't load any faster, you only unfreeze your main GUI.
If the delay is caused in the code that loads the tree, then you should "thread" that part. I would recommend reading this sample chapter from C# in a Nutshell: http://www.albahari.com/threading/. They cover C# 4.0, but you should be able to apply most of the concepts to C# 3.0 if that's what you are using.

Categories

Resources