I have a form with a top and bottom panel.
The user will be making selections in the top panel, and each time they change a value on one key field I destroy the controls in the bottom panel, then make a time-consuming call to another application (via COM) and add a list of new controls being added. This refresh process takes several seconds.
I'd like to be able to disable the bottom panel while it's being refreshed, and allow the user to be able to keep working in the top panel. Of course, this is all one GUI running on one thread.
Illustrated:
I played with BackgroundWorker, but of course it cannot directly create controls on the main thread's GUI.
Is it possible for me to do this, i.e. allow one part of the GUI to be disabled and rebuilt in the background, while the user continues to work in on another part?
Is it possible for me to do this, i.e. allow one part of the GUI to be disabled and rebuilt in the background, while the user continues to work in on another part?
In general, no. GUI elements/controls must all be created and used on the UI thread, and nowhere else.
The best way to create this type of scenario is typically to use a BackgroundWorker or other technique to get the required data on a background thread, then build your UI after the data has been loaded completely.
Related
I have created an POS application using Dynamic buttons, dynamic table layouts, and other controls in one form. The generated dynamic buttons is based on the number of data queried from the database(using OPEN ACCESS ORM).
My problem is whenever I run the application, the UI responsiveness is slow. For Example when I click on a category button, the sub category buttons appears (These are dynamic generated buttons), for it to appear, it would take few seconds to appear, then there are some little flash on the screen.
What will I do? What strategy should I perform.
Thank you. So much
Make sure the buttons do not have time consuming actions. And if they do:
use a waitcursor (simple solution, but not liked by most users)
use a thread to perform the action (might complicate other actions regarding thread safety).
I have problems with my current application which is developed in C# with WPF. The application consists of different flowcharts each contained in its own separate window.
At start-up all flowchart classes are instantiated and initialized in their window. Then the windows are made invisible and the flowchart menu appears.
With each new flowchart the application start up gets slower. The window initialization seems to consume a lot of time.
How could I approach this problem?
I thought of initialization when first needed or background initialization.
Note: I forgot a very important fact: The flowchart menu is created based on the other flowcharts, since every single flowchart is rendered as an image in order to display a thumbnail menu button. This is the problem which brough me to the performance impact anyway.
You have many approaches to this problem.
First, you have to remove the initialization from the c'tor.
Where to move it?
Either to Window_onLoad event, this way the app will first loaded and then start initializing the flow charts (using a new thread will avoid UI freeze).
Or once the user selects the required flow chart from the menu, you show the window and start initializing the inner flow chart, display a nice "loading.." animation while busy, and show the flow chart once you done.
I'd prefer the second approach, init each object when it's needed.
Edit:
Since you have to render the thumbs based on the flowcharts, i would do the following:
Move the flowcharts init to the main window Loaded event, and init each flowchart on a different thread, while busy display a nice "please wait.." animation. This way the main app window appears, the user see that the app is loading, your thumbs will be created simultaneously therefore loading time will be reduced. Once all the thumbs created, hide the animation.
Don't instantiate all the flowchart classes before you load the main window.
As a first approach I'd go with initialisation when needed.
If this proves to be unpopular as people don't like waiting then go for a background initialisation with the most popular or most recent flowchart instantiated first. This will be right most of the time so the user won't have to wait.
If you need to have a thumbnail of the flowchart then why not save the thumbnail from when the flowchart was last rendered and use that? So, when the flowchart is created first saved save a thumbnail at that point. Then when you populate the list pull that out of the database/off disk and render that.
Nobody's mentioned profiling yet, but why not just try (the last paragraph of) this?
You will easily see the dominant reason for the long time being taken.
Chances are, it's something fairly trivial that you can easily fix.
If you want more of an explanation, look here.
I am creating many usercontrols in an windows application in C# 3.5. I want to copy any usercontrol and paste it on another location of the MDIForm. Similarly in case of Cut option. I am using these three options in a contextmenustrip. And theses options are visible when I right click on the usercontrol. Can anyone tell me how It will be done at run time?
That requires giving the controls a new Parent. Explicitly supported by Winforms, they can even have no parent, quite a trick. You can do it directly by assigning the Parent property. Or by adding the control to another Controls collection, it will be automatically removed from the one it was in before.
Be careful, this flexibility comes with a price. It is also a source of a nasty leak that can crash your program after a while. That's caused by the no-parent trick, otherwise triggered by a Cut without a subsequent Paste. If you use Controls.Remove() or Controls.Clear() then the control is moved to the 'parking window', an invisible window created by the Winforms plumbing that acts as a temporary host. If you then don't either move the control to another parent or forget to call its Dispose() method then the control will live forever. Until your program runs out of resources or the user terminates the program.
The out of resources bomb ("cannot create window") typically happens after a few hours so is easily missed when debugging. You can see it in TaskMgr.exe, Processes tab. View + Select Columns and tick USER objects. Also tick GDI Objects and Handles to feel good about your program not leaking.
If you put the controls on a Panel then you can move them all together with just a single line of code by moving the panel.
You could remove the control from the ControlCollection in case of cut and cache it to add that control to some other form when pasted like you could do
panel1.Controls.Add(newPanelButton);// To add, you might have to change the control `Location` as per your need
panel1.Controls.Remove(newPanelButton);//To remove
In case of having cut/copy effect on the same form you could just change the Location of the control to the new location where you want to paste that control.
Pre .net I was using MFC, ON_UPDATE_COMMAND_UI, and the CCmdUI class to update the state of my windows UI.
From the older MFC/Win32 reference:
Typically, menu items and toolbar buttons have more than one state. For
example, a menu item is grayed
(dimmed) if it is unavailable in the
present context. Menu items can also
be checked or unchecked. A toolbar
button can also be disabled if
unavailable, or it can be checked.
Who updates the state of these items
as program conditions change?
Logically, if a menu item generates a
command that is handled by, say, a
document, it makes sense to have the
document update the menu item. The
document probably contains the
information on which the update is
based.
If a command has multiple
user-interface objects (perhaps a menu
item and a toolbar button), both are
routed to the same handler function.
This encapsulates your user-interface
update code for all of the equivalent
user-interface objects in a single
place.
The framework provides a convenient
interface for automatically updating
user-interface objects. You can choose
to do the updating in some other way,
but the interface provided is
efficient and easy to use.
What is the guidance for .net Windows Forms? I am using an Application.Idle handler in the main form but am not sure this is the best way to do this. About the time I put all my UI updates in the Idle event handler my app started to show some performance problems, and I don't have the metrics to track this down yet. Not sure if it's related.
I've found it easiest to have the menu item event handler spawn a background thread that disables the menu item, does the work, and then re-enables the menu item. That way, the UI is available to handle other UI requests, and I don't need to poll for when the operation is complete.
I usually include logic that prevents more than one operation that uses the same resources to happen simultaneously. This means creating a function to disable/enable all similar resources at once. e.g. I might only allow 1 file operation to happen at a time, so I would create a function to disable/enable all the menu items associated with file operations and call it from every one of those menu items.
Just change their property, e.g.
obj.Enabled = true;
or
obj.Enabled = false;
The property of that object will automatically call .Invalidate() or .Refresh() for you, so the control should be repainted automatically.
If you want to do a BIG task which would block the UI for multiple seconds, it's worth using Threads + Delegates.
AFAIK, in the standard .NET System.Windows.Forms world, this functionality is not available out the box.
This problem can be answered in a few ways. The links below are useful resources:
•OnUpdate equivalent
•ActionLists for Windows forms
•Command UI Updating Windows Forms in C#
No other control does this other than the scrollbars of panels, etc. Clicking and holding a button, a label, a link, a tab, whatever other control does not have this effect. But as soon as a user clicks the scrollbar, or clicks and drags the scrollbar, all other processing on the UI thread is halted. This is something that is a big problem for my application (a game, which needs to keep running in this circumstance), but I can't figure out a way to deal with this through overloads, adding in Application.DoEvents calls, or anything like that. Any thoughts?
It sounds to me like you should try to move your game logic in a different thread (as opposed to having your game logic run inside of the main UI thread).
I don't think there is any way to disable the behavior of the scrollbars. Unless your create your own controls and provide your own scrolling functionality for the containers that need it.
Write your own scrollbars/scrollable panels. Scrollbars are the ugliest/clunkiest controls in Windows anyway (except for all the others).
As soon as you start your game get off of the main thread, and do all your business logic there, but, you will need to deal with the problem that all the winform controls can only be updated by the event thread.
You will need to use InvokeRequired on the controls before changing them.
This will help get you started:
http://msdn.microsoft.com/en-us/library/ms171728%28VS.80%29.aspx
Or resize it so the scrollbars aren't needed, or move additional functions they'd normally scroll to to other controls (menu, button)